[Announcement] Working example MyBatis 3.0 web application

713 views
Skip to first unread message

Nathan Maves

unread,
Jun 30, 2010, 12:34:08 AM6/30/10
to mybati...@googlegroups.com
http://mybatis.googlecode.com/svn/sub-projects/contact_manager

The development stack is stripes+guice+mybatis+hsqldb+junit4+mockito.

It's using a couple of new features:
- package level configuration by convention available in the
programmatic config API
- and the new SqlSessionManager (available in the current snapshot
and will be in the next release)

Feel free to check it out and build the war file. Only have to drop
it into any container and you are good to go. We have changed it from
pgSql to an in memory DB (hsqldb) to make life even easier.

More to come! When I get a chance I will add a few more simple table
to show joins and other common features.

MyBatis Team

Simon

unread,
Jun 30, 2010, 10:25:35 AM6/30/10
to mybatis-user
This is great, thanks.

I have attempted to point it at oracle, with varing degress of success
(one test fails with: Caused by: java.sql.SQLException: Invalid
column type)

Here is what I did:
1) create an oracle schema/user:

CREATE USER IBATISDEMO
IDENTIFIED BY <password>
DEFAULT TABLESPACE USERS
TEMPORARY TABLESPACE TEMP
PROFILE DEFAULT
ACCOUNT UNLOCK;
GRANT CONNECT TO IBATISDEMO;
GRANT RESOURCE TO IBATISDEMO;
ALTER USER IBATISDEMO DEFAULT ROLE ALL;
GRANT CREATE SEQUENCE TO IBATISDEMO;
GRANT CREATE SYNONYM TO IBATISDEMO;
GRANT CREATE DATABASE LINK TO IBATISDEMO;
GRANT UNLIMITED TABLESPACE TO IBATISDEMO;
GRANT CREATE TABLE TO IBATISDEMO;
GRANT CREATE TRIGGER TO IBATISDEMO;
GRANT CREATE ROLE TO IBATISDEMO;
GRANT CREATE VIEW TO IBATISDEMO;
GRANT CREATE PROCEDURE TO IBATISDEMO;
GRANT CREATE TYPE TO IBATISDEMO;
ALTER USER IBATISDEMO QUOTA UNLIMITED ON USERS;

2) Run a modified version of create_schema.sql (the sequence syntax is
different for Oracle:

CREATE TABLE contact (
id integer NOT NULL,
firstName varchar(25) NULL,
lastName varchar(25) NULL,
phone varchar(25) NULL,
email varchar(25) NULL
)
/
ALTER TABLE contact ADD CONSTRAINT pk_contact PRIMARY KEY (id)
/
CREATE SEQUENCE ids INCREMENT BY 1 START WITH 1;

3) Hack WebModule.java. I could not figure out how to tell the app how
to get my jdpc class files and parameters - they seem to be hard
coded. If there is a better way please let me know

public DataSource getDataSource() {
/*
the old code:

JDBCDataSource ds = new JDBCDataSource();
ds.setUser(settings.getDatabase().getUser());
ds.setDatabase(settings.getDatabase().getDatabaseName());
*/

OracleDataSource ds;
try {
ds = new OracleDataSource();
} catch (SQLException e) {
throw new RuntimeException("Unable to get an oracle datasource",
e);
}
ds.setDriverType("thin");
ds.setServerName("oracle.mydomain.com");
ds.setPortNumber(1521);
ds.setDatabaseName("orcl"); // sid
ds.setUser("IBATISDEMO");
ds.setPassword("yourpasswordhere");

// validate connection pool setup
if (!validateDataSource(ds)) {
throw new RuntimeException("Unable to validate data source.");
}
return ds;
}

4) I gave up trying to get eclipse to build this project, I guess
becuase of the dependencies on the environtment files (which ill rip
out later, not a fan of putting the passwords and connection strings
of the prod env in the disritbution).

5) to build it, you need to do it via command line (eclipse builds the
classes ok, just cant produce a war).
mvn -Pdev test war:war

If you leave out the test, it builds a war. However:

6) One test fails, and Ive no idea what sql it was trying to execute
or where in the code it happens (the down side of using a persistence
layer I suppose). Has anyone worked out how to get the tests to run
in ecllipse?

-------------------------------------------------------------------------------
Test set: org.sample.mybatis.mappers.ContactMapperTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 3.266
sec <<< FAILURE!
crudOperations(org.sample.mybatis.mappers.ContactMapperTest) Time
elapsed: 3.032 sec <<< ERROR!
java.lang.reflect.UndeclaredThrowableException
at $Proxy7.insert(Unknown Source)
at
org.apache.ibatis.session.SqlSessionManager.insert(SqlSessionManager.java:
149)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:
54)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:35)
at $Proxy9.insert(Unknown Source)
at
org.sample.mybatis.mappers.ContactMapperTest.crudOperations(ContactMapperTest.java:
46)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod
$1.runReflectiveCall(FrameworkMethod.java:44)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:
15)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:
41)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:
20)
at
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:
28)
at
org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:
31)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:
73)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:
46)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:
28)
at
org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:
31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at
org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:
62)
at
org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:
140)
at
org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:
127)
at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:
345)
at
org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:
1009)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.ibatis.session.SqlSessionManager
$SqlSessionInterceptor.invoke(SqlSessionManager.java:222)
... 34 more
Caused by: org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause:
org.apache.ibatis.type.TypeException: Error setting null parameter.
Most JDBC drivers require that the JdbcType must be specified for all
nullable parameters. Cause: java.sql.SQLException: Invalid column type
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### Cause: org.apache.ibatis.type.TypeException: Error setting null
parameter. Most JDBC drivers require that the JdbcType must be
specified for all nullable parameters. Cause: java.sql.SQLException:
Invalid column type
at
org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:
8)
at
org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:
104)
at
org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:
91)
... 39 more
Caused by: org.apache.ibatis.type.TypeException: Error setting null
parameter. Most JDBC drivers require that the JdbcType must be
specified for all nullable parameters. Cause: java.sql.SQLException:
Invalid column type
at
org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:
17)
at
org.apache.ibatis.executor.parameter.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:
73)
at
org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:
61)
at
org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:
43)
at
org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:
56)
at
org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:
28)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:
72)
at
org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:
43)
at
org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:
102)
... 40 more
Caused by: java.sql.SQLException: Invalid column type
at
oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:
112)
at
oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:
146)
at
oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:
208)
at
oracle.jdbc.driver.OracleStatement.getInternalType(OracleStatement.java:
3456)
at
oracle.jdbc.driver.OraclePreparedStatement.setNullCritical(OraclePreparedStatement.java:
4292)
at
oracle.jdbc.driver.OraclePreparedStatement.setNull(OraclePreparedStatement.java:
4281)
at
org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:
15)
... 48 more

Larry Meadors

unread,
Jun 30, 2010, 10:41:50 AM6/30/10
to mybati...@googlegroups.com
I wish I got bug reports this good from all of my users. :D

The stack trace shows that it's here:

org.sample.mybatis.mappers.ContactMapperTest.crudOperations(ContactMapperTest.java:46)

That's the insert, but I set everything except the id which we're
getting in the sql map...unless Nathan changed it to work with hsqldb.

Which he did...sunuva. :-)

OK, so you'll need to change that for Oracle to look something like this:

<insert id="insert">
<selectKey resultType="integer" order="BEFORE" keyProperty="id">
select ids.nextval as value from dual
</selectKey>
insert into contact (
id, lastName, firstName, phone, email
) values (
#{id}, #{lastName}, #{firstName}, #{phone}, #{email}
)
</insert>

Try that, and see if it works. It should. :-D

Larry

Larry Meadors

unread,
Jun 30, 2010, 10:49:21 AM6/30/10
to mybati...@googlegroups.com
You know, it might be nice to have a JNDI version of this, too.

As much as I loathe JNDI, it's kind of popular with some people.

Larry

Simon

unread,
Jun 30, 2010, 10:52:10 AM6/30/10
to mybatis-user
I tell a lie, the test code its failing on is:
contactMapper.insert(expected);

Is there any way to see what SQL its generating/failing?
> ...
>
> read more »

Simon

unread,
Jun 30, 2010, 11:02:33 AM6/30/10
to mybatis-user
Result! the tests work :)

Is there any way to see the SQL that it generates, to debug this sort
of stuff in future?

Many thanks!

Simon.

Nathan Maves

unread,
Jun 30, 2010, 11:25:06 AM6/30/10
to mybati...@googlegroups.com
I just added a logging page on the wiki

http://code.google.com/p/mybatis/wiki/Logging

Rob Ogilvie

unread,
Jun 30, 2010, 6:52:35 PM6/30/10
to mybati...@googlegroups.com
On Tue, Jun 29, 2010 at 21:34, Nathan Maves <nathan...@gmail.com> wrote:
> http://mybatis.googlecode.com/svn/sub-projects/contact_manager
>
> The development stack is stripes+guice+mybatis+hsqldb+junit4+mockito.

Might it be possible to factor Guice and Stripes out? I see Stripes
is more of a UI toolkit, which isn't what I'm looking at, but I'm not
familiar with Guice and am wary of trying to learn two significantly
new and different techniques at once.

It's hard for me to tell which parts of the code Guice is handling and
which parts MyBatis is handling, while I'm interested in implementing
MyBatis alone.

Thanks...

Rob

Larry Meadors

unread,
Jul 1, 2010, 12:57:51 AM7/1/10
to mybati...@googlegroups.com
On Wed, Jun 30, 2010 at 4:52 PM, Rob Ogilvie <r...@axpr.net> wrote:
> Might it be possible to factor Guice and Stripes out?

Sure - what is it you're trying to do or understand?

What kind of app are you looking for?

Larry

Rob Ogilvie

unread,
Jul 1, 2010, 9:46:05 AM7/1/10
to mybati...@googlegroups.com
On Wed, Jun 30, 2010 at 21:57, Larry Meadors <larry....@gmail.com> wrote:
> On Wed, Jun 30, 2010 at 4:52 PM, Rob Ogilvie <r...@axpr.net> wrote:
>> Might it be possible to factor Guice and Stripes out?
>
> Sure - what is it you're trying to do or understand?

Thanks! The Guice stuff is a different paradigm than I'm used to; I
just need to wrap my head around the implementation of MyBatis. An
example that grabs data out of a single table and drops it into an
array of objects would probably be enough for me to run with. I
unfortunately got lost in the Guice stuff when I looked at your
example, not knowing which parts were Guice-isms and which parts were
MyBatis requirements.

> What kind of app are you looking for?

I'm writing a GWT app, but the DAO layer is just regular Java. The
only external libraries I'm using are JUnit, Mockito, GWT (not in the
DAO layer), and of course MyBatis. Anything from a simple servlet to
something that spits table data out on the console would work if it's
not using cool new stuff like Guice. :-)

Thanks!

Rob

Nathan Maves

unread,
Jul 1, 2010, 12:02:48 PM7/1/10
to mybati...@googlegroups.com
To be honest people were asking for a simple webabpp as an example.
We don't have the time or energy(unless we are paid :) to make 10
different varieties of the webapp to use everyones favorite stack. So
we took what we use every day and threw it together.

I can't tell you the last time I actually had to write a pure servlet.
Sound like you are asking for a simple Main.java which would do a
query and maybe some updates/inserts/deletes.

Rob Ogilvie

unread,
Jul 1, 2010, 12:45:24 PM7/1/10
to mybati...@googlegroups.com
On Thu, Jul 1, 2010 at 09:02, Nathan Maves <nathan...@gmail.com> wrote:
> To be honest people were asking for a simple webabpp as an example.
> We don't have the time or energy(unless we are paid :) to make 10
> different varieties of the webapp to use everyones favorite stack.  So
> we took what we use every day and threw it together.

I can respect that, and definitely appreciate the effort put in to the
example that is out there.

> I can't tell you the last time I actually had to write a pure servlet.

I wrote one a few months ago. Count your blessings.

>  Sound like you are asking for a simple Main.java which would do a
> query and maybe some updates/inserts/deletes.

Exactly; I just need a basic example of MyBatis. I don't need the
rest of the cool stuff, which unfortunately obfuscated the simplicity
of MyBatis /for me/...

Anything you can do is appreciated. Worst case, I'll just have to
learn Guice, too, which would be an unfortunate delay but might be
beneficial in the long run.

Rob

Larry Meadors

unread,
Jul 1, 2010, 12:56:18 PM7/1/10
to mybati...@googlegroups.com
A command line app might be pretty simple/quick to bang out.

Larry


PS: Sorry about having to write a servlet. That sucks. :-)

Guy Rouillier

unread,
Jul 1, 2010, 1:43:06 PM7/1/10
to mybati...@googlegroups.com
On 7/1/2010 12:45 PM, Rob Ogilvie wrote:
>> Sound like you are asking for a simple Main.java which would do a
>> query and maybe some updates/inserts/deletes.
>
> Exactly; I just need a basic example of MyBatis. I don't need the
> rest of the cool stuff, which unfortunately obfuscated the simplicity
> of MyBatis /for me/...

I have a basic single file Java command line program that I use to test
things out with iBATIS. I'd gladly share it; where can I post it? I
put some code up on the wiki whiteboard a couple months ago (Oracle
stored proc example, which others have been asking for here), but that
appears to have been wiped clean. So, where do user contributions go now?

--
Guy Rouillier

Vijay Kumar

unread,
Jul 29, 2010, 2:32:31 PM7/29/10
to mybatis-user
Guy,
If it;s just one class with a couple of config files, can you just
post your code as text in this email thread, That would be most
beneficial to the users. I am migrating my code from iBatis 2 to
MyBatis 3.0 and having a hard time. I would also appreciate if you
can email me your code as an attachment.

I have this SQLMappingMBean from iBatis 2 and can't find a replacement
for it.

import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;

import javax.ejb.EJBException;

import org.jboss.annotation.ejb.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;

@Service(objectName="dps-service:service=sqlMapping")
public class SqlMappingMBean implements SqlMapping {

private static final Logger logger =
LoggerFactory.getLogger(SqlMappingMBean.class);
private static String DEFAULT = SqlMappingMBean.class.getName() +
".DEFAULT";

private String sqlMapConfig = "ibatis/SqlMapConfig.xml,prep:ibatis/
PrepSqlMapConfig.xml";
private Map<String, SqlMapClient> sqlMapClient;

public void create() throws Exception {
// TODO Auto-generated method stub

}

public void destroy() {
// TODO Auto-generated method stub

}

public void start() throws Exception {
// TODO Auto-generated method stub

}

private void internalStart() {
logger.info("Starting iBATIS SQL map client service");
sqlMapClient = new HashMap<String, SqlMapClient>();
Map<String, String> maps = parse(sqlMapConfig);
for (Map.Entry<String, String> entry : maps.entrySet()) {
logger.info("Reading SQL map configuration for " +
getDisplayName(entry.getKey()) + " from: " + entry.getValue());
sqlMapClient.put(entry.getKey(),
getSqlMapClient(entry.getValue()));
}
}

public void stop() {
logger.info("Stopping iBATIS SQL map client service");
sqlMapClient = null;
}

public SqlMapClient getInstance() {
return getInstance(DEFAULT);
}

public SqlMapClient getInstance(String name) {
// Lazy instantiation due to https://jira.jboss.org/jira/browse/JBAS-7092
if (sqlMapClient == null)
internalStart();
return sqlMapClient.get(name);
}


public void flushDataCache() {
if (sqlMapClient == null)
logger.info("No SQL map client instance");
else {
for (Map.Entry<String, SqlMapClient> entry :
sqlMapClient.entrySet()) {
logger.info("Flushing SQL map client data cache for " +
entry.getKey());
entry.getValue().flushDataCache();
}
}
}

public String getSqlMapConfig() {
return sqlMapConfig;
}

public void setSqlMapConfig(String sqlMapConfig) {
this.sqlMapConfig = sqlMapConfig;
}

private static Map<String, String> parse(String string) {
Map<String, String> pairs = new HashMap<String, String>();
boolean haveDefault = false;
for (String map : string.split(",")) {
String[] pair = map.split(":");
switch (pair.length) {
case 1:
if (! haveDefault) {
pairs.put(DEFAULT, pair[0].trim());
haveDefault = true;
} else
throw new IllegalArgumentException("Map specification list
includes more than one unnamed map specification: " + string);
break;
case 2:
pairs.put(pair[0].trim(), pair[1].trim());
break;
default:
throw new IllegalArgumentException("Invalid map specification: " +
string);
}
}
return pairs;
}

private static SqlMapClient getSqlMapClient(String sqlMapConfig) {
Reader reader = null;
try {
reader = Resources.getResourceAsReader(sqlMapConfig);
return SqlMapClientBuilder.buildSqlMapClient(reader);
} catch (Exception e) {
throw new EJBException("Error reading SQL map configuration from: "
+ sqlMapConfig, e);
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
logger.error("Error closing reader", e);
}
}
}

private static String getDisplayName(String name) {
return name.equals(DEFAULT) ? "(default)" : name;
}
}





On Jul 1, 12:43 pm, Guy Rouillier <g...@burntmail.com> wrote:
> On 7/1/2010 12:45 PM, Rob Ogilvie wrote:
>
> >>   Sound like you are asking for a simple Main.java which would do a
> >> query and maybe some updates/inserts/deletes.
>
> > Exactly; I just need a basicexampleof MyBatis.  I don't need the
> > rest of the cool stuff, which unfortunately obfuscated the simplicity
> > of MyBatis /for me/...
>
> I have a basic single file Java command line program that I use to test
> things out with iBATIS.  I'd gladly share it; where can I post it?  I
> put some code up on the wiki whiteboard a couple months ago (Oracle
> stored procexample, which others have been asking for here), but that

Guy Rouillier

unread,
Aug 9, 2010, 12:34:33 AM8/9/10
to mybati...@googlegroups.com

Sorry for the long delay, but I've finally implemented a version of the
contact_manager sample application that is a simple command line program
without all the webapp wrapping. I also unraveled some of the
directories as I didn't think the deep nesting was necessary. I'm going
to submit this example as mybatis_contact_manager_cli. Hopefully it
will show up in the repository soon.

When I have time in the next couple days, I'll add a simple example of
calling an Oracle stored procedure.

--
Guy Rouillier

Clinton Begin

unread,
Aug 9, 2010, 1:36:40 AM8/9/10
to mybati...@googlegroups.com
Guy, I tried to contact you directly, but it didn't seem to get to you.  I think we can just give you SVN access.  Send me a private mail and we'll get you set up.


Clinton

Guy Rouillier

unread,
Aug 9, 2010, 1:37:01 AM8/9/10
to mybati...@googlegroups.com
On 8/9/2010 12:34 AM, Guy Rouillier wrote:
> Sorry for the long delay, but I've finally implemented a version of the
> contact_manager sample application that is a simple command line program
> without all the webapp wrapping. I also unraveled some of the
> directories as I didn't think the deep nesting was necessary. I'm going
> to submit this example as mybatis_contact_manager_cli. Hopefully it will
> show up in the repository soon.

See issue 78: http://code.google.com/p/mybatis/issues/detail?id=78

--
Guy Rouillier

bryan0101

unread,
Aug 10, 2010, 2:48:39 PM8/10/10
to mybatis-user
Hi,
Just a small question for guice: why 1.0 is being used when 2.0 is
in GA from 2009? Are there any deal breakers in 2.0 that prevent
mybatis from using it?
Thanks
Bryan

Simone Tripodi

unread,
Aug 10, 2010, 3:16:32 PM8/10/10
to mybati...@googlegroups.com
Hi Bryan,
take a look at the mybatis-guice subproject[1] (1.0.0-snapshot is
going to be released) to see how we're integrating Guice2 with
MyBatis.
If you checkout the code, lunching 'mvn package' the user manual will
be created as well (apologize in advance for my English!), every
feedback is more than welcome.
All the best,
Simo

[1] http://mybatis.googlecode.com/svn/sub-projects/mybatis-guice/trunk

http://people.apache.org/~simonetripodi/
http://www.99soft.org/

Reply all
Reply to author
Forward
0 new messages