Coder Social home page Coder Social logo

guice's Introduction

MyBatis Guice Module

Java CI Coverage Status Maven central Sonatype Nexus (Snapshots) License

mybatis-guice

The MyBatis Guice module is easy-to-use Google Guice bridge for MyBatis sql mapping framework.

Essentials

guice's People

Contributors

alexey-su avatar berniegp avatar christianpoitras avatar dave-r12 avatar dependabot-preview[bot] avatar dependabot[bot] avatar emacarron avatar georgantasp avatar harawata avatar hazendaz avatar hboutemy avatar jeffgbutler avatar johnzeringue avatar kazuki43zoo avatar kenil121200 avatar lazeyliu avatar littson avatar marcosperanza avatar mox601 avatar nmaves avatar nw-engineer avatar phantomydn avatar renovate[bot] avatar robotdan avatar sgdesmet avatar simonetripodi avatar wcong avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

guice's Issues

Configuration Variables

Currently there is no way of changing variables in the default Configuration (org.apache.ibatis.session.Configuration) generated by mybatis-guice.

If you want to use variables assigned to the current Configuration in the mapper files (xml), you need to call config.getVariables().put() before the mapper xml files are parsed.

With the current mybatis-guice layout you can't.

I'm using:
mybatis-guice-3.3

AOP synthetic warnings in java8

Noticed this issue when having @Transactional annotation on methods of repository classes that implement some interfaces with generics:

https://groups.google.com/forum/#!topic/google-guice/-DH5fBD7M30

Did this in my module, the problem is gone and everything looks OK:

...
protected static final AbstractMatcher<Method> SYNTHETIC = new AbstractMatcher<Method>() {
    @Override
    public boolean matches(Method method) {
        return method.isSynthetic();
    }
};

...
@Override
protected void bindTransactionInterceptors() 
{
  TransactionalMethodInterceptor interceptor = new TransactionalMethodInterceptor();
  requestInjection(interceptor);
  bindInterceptor(any(), not(SYNTHETIC).and(not(DECLARED_BY_OBJECT).and(annotatedWith(Transactional.class))), interceptor);

  // Intercept classes annotated with Transactional, but avoid "double"
  // interception when a mathod is also annotated inside an annotated
  // class.
  bindInterceptor(annotatedWith(Transactional.class), 
      not(SYNTHETIC).and(not(DECLARED_BY_OBJECT).and(not(annotatedWith(Transactional.class)))), interceptor);
}

If this is ok, I suppose bindTransactionInterceptors() can implement this change in mybatis-guice?

mybatis-guice JdbcHelper Oracle Thin URL not compatible with all formats

In JdbcHelper:
Oracle_Thin("jdbc:oracle:thin:@${JDBC.host|localhost}:${JDBC.port|1521}:${oracle.sid|ORCL}", "oracle.jdbc.OracleDriver"),

Does not support Thin-style Service Name Syntax (http://docs.oracle.com/cd/B14117_01/java.101/b10979/urls.htm#BEIDHCBA)

For example the following URL cannot be used successfully:

jdbc:oracle:thin:@//127.0.0.1:1521/SERVICEABC"

One can hack the JDBC.host part to pass in "//127.0.0.1", but oracle.sid will always be preceded by a ":".

I "hacked" my local project to create a custom Helper in the same package as JdbcHelper (to obtain access to Formatter), but the real solution would be to update the URL in the enum to read

jdbc:oracle:thin:@${JDBC.host|localhost}:${JDBC.port|1521}/${oracle.sid|ORCL}"

The "/" before oracle.SID would work for both Services and SIDs.

Thanks

Specifying multiple independent JDBC URLs to try?

Currently I specify a single JDBC.url in the properties file I pass to:

Names.bindProperties(binder(), properties);

I know some DBs support specifying failovers in the JDBC URL itself. However we would like to specify multiple completely independent JDBC URLs for our read only datasource and then have MyBatis Guice try them in turn until it gets a valid connection.

Is this possible or is there a simple path to implementing it on top of the existing functionality?

Uses optional dependencies in OSGI

The problem in the new version repeats the error #9.
It is necessary to change the dependencies. Add the package com.alibaba.druid.pool in pom.xml.

    <osgi.import>
      com.alibaba.druid.pool.*;resolution:=optional,
      com.jolbox.bonecp.*;resolution:=optional,
      com.mchange.v2.c3p0.*;resolution:=optional,
      org.apache.commons.dbcp.*;resolution:=optional,
      javax.transaction.*;resolution:=optional,
      *
    </osgi.import>

mybatis-guice test success depends on order

Many tests expects the contact object to have an id. But the contact's id is available only after a test actually inserts it in the database. Otherwise, the contact's id will be null or invalid causing error in multiple tests like AbstractMyBatisModuleTestCase.selectContact.

The database should be cleaned properly between each test so that test order does not matter.

Constructor Injection for TypeHandlers doesn't work.

I see that this is related to #30 .

When trying to upgrade to the latest version, that fix is breaking many of my typehandlers which need constructor injection.

As the original issue is described, I think the existing solution is too heavy handed. I'll propose a different solution shortly.

Transactional doesn't work in private module when exposing the interface instead of the implementation

See this gist.

This main fails at this point:

Exception in thread "main" java.lang.RuntimeException: Not transactional at com.mirkorossini.transactionaltest.Test.testTransactional(Test.java:51) at com.mirkorossini.transactionaltest.Test.main(Test.java:78) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

Notice that it only happen if I expose the SqlSessionManager explicitely, and only if I bind the interface instead of the implementation directly.

I also explain the issue more extensively here.

Cannot set configuration fields using properties

Binding properties may not work anymore after fix #79.

properties.put("mybatis.configuration.defaultStatementTimeout", "10");
Names.bindProperties(binder(), properties);

Need to use this syntax now.

bindConfigurationSetting(configuration -> configuration.setDefaultStatementTimeout(10));

See issue #42.

Setting mapUnderscoreToCamelCase not revealed in MyBatisModule abstract class

It looks like this configuration setting was added to the ConfigurationProvider but was not revealed in the MyBatisModule abstract class. Instead, it looks like users have to set it like this:

bindConstant().annotatedWith(Names.named("mybatis.configuration.mapUnderscoreToCamelCase")).to(true);

It would be better if we could use a method like this:

mapUnderscoreToCamelCase(true);

Here's the code for that method on MyBatisModule:

    /**
     * Maps underscores to camel case.
     *
     * @param mapUnderscoreToCamelCase Toggles this settings value.
     */
    protected final void mapUnderscoreToCamelCase(boolean mapUnderscoreToCamelCase) {
        bindBoolean("mybatis.configuration.mapUnderscoreToCamelCase", mapUnderscoreToCamelCase);
    }

Cannot register "generic" type handler in MyBatisModule

MyBatis has a feature where you can declare a type handler class that has a single one-arg constructor, and the type handler is constructed with a different target type on each mapping.

In mybatis-guice the type handlers are always instantiated immediately on configuration, so mybatis doesn't check for a constructor, nor does it provide any other way to determine the desired output type of such a "generic" type handler.

Ideally it would be possible to take advantage of this mybatis feature easily with mybatis-guice.

Cannot handle multiple types with one generic type provider

Issue #30 add feature to define generic type providers, but it does not solve the problem - we can use such "generic" provider only once. (I.e. in code example we cannot use such type provider to bind to 2+ classes) For example, when we have provider

class GenericCustomObjectTypeHandler<E extends CustomObject> extends BaseTypeHandler<E>

it can be used to handle type CustomObject

protected void initialize() {
  Class handlerClass = (Class)GenericCustomObjectTypeHandler.class;
  handleType(CustomObject.class).with(handlerClass);
}

But when we cannot do this:

protected void initialize() {
  Class handlerClass = (Class)GenericCustomObjectTypeHandler.class;
  handleType(CustomObjectA.class).with(handlerClass);
  handleType(CustomObjectB.class).with(handlerClass);
}

(both classes CustomObjectA and CustomObjectB extends CustomObject)

To fix this injection of TypeLiteral for ObjectTypeHandler should be implemented to be able to call:

protected void initialize() {
  handleType(CustomObjectA.class).with(new TypeLiteral<GenericCustomObjectTypeHandler<CustomObjectA>>() {});
  handleType(CustomObjectB.class).with(new TypeLiteral<GenericCustomObjectTypeHandler<CustomObjectB>>() {});
}

Incorrect value for idleConnectionTestPeriod for BoneCP

There is a configuration error in BoneCPProvider which results in idleConnectionTestPeriod to be invariably set in seconds.

idleConnectionTestPeriodInMinutes and idleConnectionTestPeriodInSeconds should be created to set the value in minutes or seconds.

TransactionalMethodInterceptor: Rethrow original Throwable by default

Hi,

In TransactionalMethodInterceptor:

        // check the caught exception is declared in the invoked method
        for (Class<?> exceptionClass : interceptedMethod.getExceptionTypes()) {
            if (exceptionClass.isAssignableFrom(t.getClass())) {
                return t;
            }
        }

        // check the caught exception is of same rethrow type
        if (transactional.rethrowExceptionsAs().isAssignableFrom(t.getClass())) {
            return t;
        }

        // rethrow the exception as new exception

I was wondering why the last option is to rethrow as new?
I was thinking it should be: if transactional.rethrowExceptionsAs() != null, do the rethrow, otherwise just throw the original Throwable.

Why?
If I have

@Transactional
public void updatePlan(Plan p) {
   
}

And in some other class

 ...
  try {
          PlanService.updatePlan(p);
  catch (NoSuchSLAException e) {
           // do something
  }

The current implementation forces to declare NoSuchSLAException on updatePlan() (it's a RuntimeException). Though it seems like a good design choice, the @transactional shouldn't really force you to make that choice.

Since I haven't, it rethrows this exception as Exception() containing my NoSuchSLAException.
So as soon as I take an existing code, and annotate it with @transactional I break existing code.

It seems reasonable to rethrow as new only if you explicitly asked for it by specifying rethrowExceptionAs attribute on the Transaction annotation.

Funny thing is that when you look at TxTransactionalMethodInterceptor you see that:

            } catch (Throwable t) {
                if(log.isDebugEnabled()) {
                    log.debug(format("%s - Tx Transaction %s (CompletionAllowed %s) rolling back",
                            debugPrefix,
                            attribute.name(),
                            tranToken.isCompletionAllowed()));
                }
                manager.setRollbackOnly();
                throw t;

No conversion done from to to a new exception, even though this interceptor uses the same Transactional annotation.

So I was wondering what was the motivation and if this change ok?

Incorrect generics for PerUserPoolDataSourceModule

In PerUserPoolDataSourceModule, it is not allowed to set a subclass of Provider<Map, Boolean> for setPerUserDefaultAutoCommitProviderClass() method. This makes no sense since Provider is an interface.

This applies to all providers in PerUserPoolDataSourceModule.

JTA Module Does Not Support Chained @Transactional Methods

In a small demo project I wrote, I found that when using the JTA Module if a @transactional method calls another @transactional method, then the interceptor will fail.

Because of JTA complexities, there are likely a wide variety of methods combinations that should work. For example,

@transactional method1 calling @transactional method2 - method2 should be a part of the same transaction as method1 (both of these annotations default to REQUIRED which is a reasonable default and should just work). I think this is by far the most common use case.

@transactional method1 calling @transactional(NEVER) method2 - I think this should fail.

@transactional method1 calling @transactional(REQUIRES_NEW) method2 - method2 should start a new nested transaction.

etc.

This can get complex very quickly, but we should probably attempt to support the more common use cases.

Generic TypeHandlers not working with XML config.

My issue seems to be related to #82 and #30:

I'm using an XMLMyBatisModule setup with a generic TypeHandler to convert between Java objects and postgres Json data fields. During initialization I get:

org.apache.ibatis.type.TypeException: Unable to find a usable constructor for class com.calverteducation.jvirgil.mybatisDao.typeHandler.JsonTypeHandler
  at org.mybatis.guice.XMLMyBatisModule.internalConfigure(XMLMyBatisModule.java:119)

Looking at the other issues, it seem like this problem may already be solved with a java-based configuration, but XML config is still a valid option (that I'm currently using) so the fix should work there as well.

.gitattributes on a mac

Hi, I recently was struggling to work on your repo with this setting on my mac. When I check out master, it was converting line endings for every file to LF.
Looking at this documentaion I believe it is a little ambiguous as to what this line will do:

  • text=auto

This documentation explains the issue.

This setup should leave you with CRLF endings in Windows checkouts, but LF endings on Mac and Linux systems and in the repository.

If you want your repo to contain the CRLF endings, I think you should change the file to this:

  • text=crlf

JDK version to use for mybatis

Please let me know the jdk version compatable for mybatis to support sqlsessionfactorybean to replace sqlclientfactorybean of ibatis.

MyBatisModule uses internal guice dependencies

The MyBatisModule uses static imports against internal guice dependencies.

import static com.google.inject.internal.util.$Preconditions.checkArgument;
import static com.google.inject.internal.util.$Preconditions.checkState;

It is expected that the guice team will use public guice apis so other versions of guice can be used with MyBatis-Guice.

java.lang.NoClassDefFoundError: com/google/inject/internal/util/$Preconditions
       at org.mybatis.guice.MyBatisModule.internalConfigure(MyBatisModule.java:84)
       at org.mybatis.guice.AbstractMyBatisModule.configure(AbstractMyBatisModule.java:59)
       at com.google.inject.AbstractModule.configure(AbstractModule.java:62)
       at com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:230)
       at com.google.inject.PrivateModule.install(PrivateModule.java:183)

[note] Migrated from https://code.google.com/p/mybatis/issues/detail?id=574

MyBatis-Guice multiple datasource configuration does not work with JNDI datasources

Is it expected that JNDI datasources should work using the Multiple Datasources configuration advice given at
http://mybatis.github.com/guice/core.html
??

We spent a great deal of time reading doc and forums - both before and after we encountered the problem described below - but could find nothing related.

We needed to add an additional datasource to the application that has been running fine with a single JNDI connection configured using the MyBatisModule directly.

When we used a PrivateModule to wrap each of our MyBatisModules for the two datasources we get the message:
null returned by binding at org.mybatis.guice.MyBatisModule.bindDataSourceProviderType(MyBatisModule.java:215) ... while locating javax.sql.DataSource

After tracing and checking for hours, we finally got this to work by using direct JDBC with the PooledDataSourceProvider.class.

I've attached three files:

  • the log from Tomcat showing the detailed exceptions we get.
  • The AppListener module configured with JNDI that fails.
  • The AppListener module configured with direct JDBC

The two modules are identical except for the lines I've commented out by each. A quick diff will show.

Thank you.

Log from Tomcat showing the detailed exceptions we get:

Mar 23, 2013 12:14:48 PM org.apache.catalina.core.AprLifecycleListener init
INFO: Loaded APR based Apache Tomcat Native library 1.1.23 using APR version 1.4.6.
Mar 23, 2013 12:14:48 PM org.apache.catalina.core.AprLifecycleListener init
INFO: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
Mar 23, 2013 12:14:48 PM org.apache.catalina.startup.SetAllPropertiesRule begin
WARNING: [SetAllPropertiesRule]{Server/Service/Connector} Setting property 'clientAuth' to 'false' did not find a matching property.
Mar 23, 2013 12:14:48 PM org.apache.tomcat.util.digester.SetPropertiesRule begin
WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:extranet' did not find a matching property.
Mar 23, 2013 12:14:48 PM org.apache.catalina.core.AprLifecycleListener initializeSSL
INFO: OpenSSL successfully initialized with version OpenSSL 1.0.0g 18 Jan 2012
Mar 23, 2013 12:14:49 PM org.apache.coyote.http11.Http11AprProtocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
Mar 23, 2013 12:14:49 PM org.apache.coyote.http11.Http11AprProtocol init
INFO: Initializing Coyote HTTP/1.1 on http-8443
Mar 23, 2013 12:14:49 PM org.apache.coyote.ajp.AjpAprProtocol init
INFO: Initializing Coyote AJP/1.3 on ajp-8009
Mar 23, 2013 12:14:49 PM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 789 ms
Mar 23, 2013 12:14:49 PM org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
Mar 23, 2013 12:14:49 PM org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.36
[DEBUG] 2013-03-23 12:14:49,487 (AppListener.java:getInjector:122) sm1=com.trumpetinc.environment.AppListener$1@2322bce
[DEBUG] 2013-03-23 12:14:49,489 (AppListener.java:getInjector:123) pm1=com.trumpetinc.environment.AppListener$2@1664023c
[DEBUG] 2013-03-23 12:14:49,489 (AppListener.java:getInjector:124) pm2=com.trumpetinc.environment.AppListener$3@7fcebc9f
[DEBUG] 2013-03-23 12:14:49,668 (LogFactory.java:setImplementation:120) Logging initialized using 'org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
Mar 23, 2013 12:14:49 PM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class com.trumpetinc.environment.AppListener
com.google.inject.CreationException: Guice creation errors:

1) null returned by binding at org.mybatis.guice.MyBatisModule.bindDataSourceProviderType(MyBatisModule.java:215)
 but org.mybatis.guice.environment.EnvironmentProvider.dataSource is not @Nullable
  while locating org.mybatis.guice.datasource.builtin.JndiDataSourceProvider
  at org.mybatis.guice.MyBatisModule.bindDataSourceProviderType(MyBatisModule.java:215)
  while locating javax.sql.DataSource
    for field at org.mybatis.guice.environment.EnvironmentProvider.dataSource(EnvironmentProvider.java:57)
  at org.mybatis.guice.environment.EnvironmentProvider.class(EnvironmentProvider.java:32)
  while locating org.mybatis.guice.environment.EnvironmentProvider
  at org.mybatis.guice.MyBatisModule.internalConfigure(MyBatisModule.java:105)
  while locating org.apache.ibatis.mapping.Environment
    for parameter 0 at org.mybatis.guice.configuration.ConfigurationProvider.<init>(ConfigurationProvider.java:116)
  at org.mybatis.guice.configuration.ConfigurationProvider.class(ConfigurationProvider.java:43)
  while locating org.mybatis.guice.configuration.ConfigurationProvider
  at org.mybatis.guice.MyBatisModule.internalConfigure(MyBatisModule.java:106)
  while locating org.apache.ibatis.session.Configuration
    for parameter 0 at org.mybatis.guice.session.SqlSessionFactoryProvider.createNewSqlSessionFactory(SqlSessionFactoryProvider.java:64)
  at org.mybatis.guice.session.SqlSessionFactoryProvider.class(SqlSessionFactoryProvider.java:31)
  while locating org.mybatis.guice.session.SqlSessionFactoryProvider
  at org.mybatis.guice.MyBatisModule.internalConfigure(MyBatisModule.java:107)
  while locating org.apache.ibatis.session.SqlSessionFactory
    for parameter 0 at org.mybatis.guice.session.SqlSessionManagerProvider.createNewSqlSessionManager(SqlSessionManagerProvider.java:55)
  at org.mybatis.guice.session.SqlSessionManagerProvider.class(SqlSessionManagerProvider.java:31)
  while locating org.mybatis.guice.session.SqlSessionManagerProvider
  at org.mybatis.guice.AbstractMyBatisModule.configure(AbstractMyBatisModule.java:51)
  while locating org.apache.ibatis.session.SqlSessionManager
    for field at org.mybatis.guice.mappers.MapperProvider.sqlSessionManager(MapperProvider.java:40)
  while locating org.mybatis.guice.mappers.MapperProvider
  at com.google.inject.util.Providers$3.initialize(Providers.java:101)
  at org.mybatis.guice.AbstractMyBatisModule.bindMapper(AbstractMyBatisModule.java:76)

2) null returned by binding at org.mybatis.guice.MyBatisModule.bindDataSourceProviderType(MyBatisModule.java:215)
 but org.mybatis.guice.environment.EnvironmentProvider.dataSource is not @Nullable
  while locating org.mybatis.guice.datasource.builtin.JndiDataSourceProvider
  at org.mybatis.guice.MyBatisModule.bindDataSourceProviderType(MyBatisModule.java:215)
  while locating javax.sql.DataSource
    for field at org.mybatis.guice.environment.EnvironmentProvider.dataSource(EnvironmentProvider.java:57)
  at org.mybatis.guice.environment.EnvironmentProvider.class(EnvironmentProvider.java:32)
  while locating org.mybatis.guice.environment.EnvironmentProvider
  at org.mybatis.guice.MyBatisModule.internalConfigure(MyBatisModule.java:105)
  while locating org.apache.ibatis.mapping.Environment
    for parameter 0 at org.mybatis.guice.configuration.ConfigurationProvider.<init>(ConfigurationProvider.java:116)
  at org.mybatis.guice.configuration.ConfigurationProvider.class(ConfigurationProvider.java:43)
  while locating org.mybatis.guice.configuration.ConfigurationProvider
  at org.mybatis.guice.MyBatisModule.internalConfigure(MyBatisModule.java:106)
  while locating org.apache.ibatis.session.Configuration
    for parameter 0 at org.mybatis.guice.session.SqlSessionFactoryProvider.createNewSqlSessionFactory(SqlSessionFactoryProvider.java:64)
  at org.mybatis.guice.session.SqlSessionFactoryProvider.class(SqlSessionFactoryProvider.java:31)
  while locating org.mybatis.guice.session.SqlSessionFactoryProvider
  at org.mybatis.guice.MyBatisModule.internalConfigure(MyBatisModule.java:107)
  while locating org.apache.ibatis.session.SqlSessionFactory
    for parameter 0 at org.mybatis.guice.session.SqlSessionManagerProvider.createNewSqlSessionManager(SqlSessionManagerProvider.java:55)
  at org.mybatis.guice.session.SqlSessionManagerProvider.class(SqlSessionManagerProvider.java:31)
  while locating org.mybatis.guice.session.SqlSessionManagerProvider
  at org.mybatis.guice.AbstractMyBatisModule.configure(AbstractMyBatisModule.java:51)
  while locating org.apache.ibatis.session.SqlSessionManager
    for field at org.mybatis.guice.transactional.TransactionalMethodInterceptor.sqlSessionManager(TransactionalMethodInterceptor.java:61)
  at org.mybatis.guice.AbstractMyBatisModule.configure(AbstractMyBatisModule.java:56)

2 errors
    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:435)
    at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:175)
    at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:109)
    at com.google.inject.Guice.createInjector(Guice.java:95)
    at com.google.inject.Guice.createInjector(Guice.java:72)
    at com.google.inject.Guice.createInjector(Guice.java:62)
    at com.trumpetinc.environment.AppListener.getInjector(AppListener.java:126)
    at com.google.inject.servlet.GuiceServletContextListener.contextInitialized(GuiceServletContextListener.java:45)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4206)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4705)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:840)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)
    at org.apache.catalina.core.StandardService.start(StandardService.java:525)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:754)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
Mar 23, 2013 12:14:50 PM org.apache.catalina.core.StandardContext start
SEVERE: Error listenerStart
Mar 23, 2013 12:14:50 PM org.apache.catalina.core.StandardContext start
SEVERE: Context [/extranet] startup failed due to previous errors
Mar 23, 2013 12:14:50 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/extranet] appears to have started a thread named [com.google.inject.internal.util.$Finalizer] but has failed to stop it. This is very likely to create a memory leak.
Mar 23, 2013 12:14:50 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/extranet] created a ThreadLocal with key of type [com.google.inject.internal.InjectorImpl$1] (value [com.google.inject.internal.InjectorImpl$1@37b82d69]) and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@1cad6513]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Mar 23, 2013 12:14:50 PM org.apache.coyote.http11.Http11AprProtocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
Mar 23, 2013 12:14:50 PM org.apache.coyote.http11.Http11AprProtocol start
INFO: Starting Coyote HTTP/1.1 on http-8443
Mar 23, 2013 12:14:50 PM org.apache.coyote.ajp.AjpAprProtocol start
INFO: Starting Coyote AJP/1.3 on ajp-8009
Mar 23, 2013 12:14:50 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 1068 ms

AppListener module configured with JNDI that fails:

package com.trumpetinc.environment;

import static com.google.inject.name.Names.bindProperties;

import java.io.IOException;
import java.util.Map.Entry;
import java.util.Properties;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import com.google.inject.Binding;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;

import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.apache.log4j.Logger;
import org.mybatis.guice.MyBatisModule;
import org.mybatis.guice.datasource.builtin.JndiDataSourceProvider;
import org.mybatis.guice.datasource.builtin.PooledDataSourceProvider;
import org.mybatis.guice.datasource.helper.JdbcHelper;

import com.google.inject.PrivateModule;
import com.google.inject.name.Names;
import com.google.inject.servlet.GuiceServletContextListener;
import com.google.inject.servlet.ServletModule;
import com.trumpetinc.goldmine.GoldMineMapper;
import com.trumpetinc.goldmine.GoldMineService;
import com.trumpetinc.goldmine.GoldMineServiceImplMyBatis;
import com.trumpetinc.livelookup.TimeZoneMapper;
import com.trumpetinc.timezone.TimeZoneLookupServlet;
import com.trumpetinc.timezone.ZipCodeTimeZoneLookupService;
import com.trumpetinc.timezone.ZipCodeTimeZoneLookupServiceImpl;

/**
 * Application Lifecycle Listener implementation class AppListener
 *
 */
// public class AppListener extends GuiceServletContextListener implements ServletContextListener, ServletContextAttributeListener, HttpSessionListener, HttpSessionAttributeListener, HttpSessionActivationListener, HttpSessionBindingListener, ServletRequestListener, ServletRequestAttributeListener
public class AppListener extends GuiceServletContextListener {

    private static final Logger log = Logger
        .getLogger(TimeZoneLookupServlet.class);    

    /**
     * @see GuiceServletContextListener#GuiceServletContextListener()
     */
    public AppListener() {
        super();
        // TODO Auto-generated constructor stub
    }

    @Override
    protected Injector getInjector() {
        ServletModule sm1 =             
            new ServletModule() {
                @Override
                protected void configureServlets() {
                    filter("/livelookup/goldmine2").through(createTransactionFilter());
                    serve("/livelookup/goldmine2").with(com.trumpetinc.livelookup.GoldmineLiveLookupServlet2.class);
                    filter("/upload").through(createTransactionFilter());
                    serve("/upload").with(com.trumpetinc.uploads.HandleUploadRequest.class);
                    filter("/timezonelookup").through(createTransactionFilter());
                    serve("/timezonelookup").with(com.trumpetinc.timezone.TimeZoneLookupServlet.class);
                }
            };
        PrivateModule pm1 = 
            new PrivateModule() {
                @Override
                protected void configure() {
                    install(new MyBatisModule() {
                        @Override
                        protected void initialize() {
                            install(JdbcHelper.SQL_Server_jTDS);
                            bindDataSourceProviderType(JndiDataSourceProvider.class);
                            // bindDataSourceProviderType(PooledDataSourceProvider.class);
                            bindTransactionFactoryType(JdbcTransactionFactory.class);
                            addMapperClass(GoldMineMapper.class);
                            // bindProperties(binder(),getJNDIConnectionProperties("TrumpetGM"));
                        }
                    });
                    Names.bindProperties(this.binder(),getJNDIConnectionProperties("TrumpetGM"));
                    // Names.bindProperties(this.binder(),getJDBCConnectionProperties("GoldMineTpt"));
                    bind(GoldMineServiceImplMyBatis.class);
                    bind(GoldMineService.class).to(GoldMineServiceImplMyBatis.class);
                    expose(GoldMineMapper.class);
                    expose(GoldMineService.class);
                    expose(GoldMineServiceImplMyBatis.class);
                }
            };
        PrivateModule pm2 =
            new PrivateModule() {
                @Override
                protected void configure() {
                    install(new MyBatisModule() {
                        @Override
                        protected void initialize() {
                            install(JdbcHelper.SQL_Server_jTDS);
                            bindDataSourceProviderType(JndiDataSourceProvider.class);
                            // bindDataSourceProviderType(PooledDataSourceProvider.class);
                            bindTransactionFactoryType(JdbcTransactionFactory.class);
                            addMapperClass(TimeZoneMapper.class);
                            // bindProperties(binder(),getJNDIConnectionProperties("TimeZoneLookup"));
                        }
                    });
                    Names.bindProperties(this.binder(),getJNDIConnectionProperties("TimeZoneLookup"));
                    // Names.bindProperties(this.binder(),getJDBCConnectionProperties("TimeZoneLookup"));
                    bind(ZipCodeTimeZoneLookupServiceImpl.class);
                    bind(ZipCodeTimeZoneLookupService.class).to(ZipCodeTimeZoneLookupServiceImpl.class);
                    expose(TimeZoneMapper.class);
                    expose(ZipCodeTimeZoneLookupService.class);
                    expose(ZipCodeTimeZoneLookupServiceImpl.class);
                }
            };

        log.debug("sm1="+sm1);
        log.debug("pm1="+pm1);
        log.debug("pm2="+pm2);

        Injector inj = Guice.createInjector(sm1,pm1, pm2 );
        for (Entry<Key<?>, Binding<?>> binding : inj.getBindings().entrySet() ) {
            log.debug(binding.getKey() + " -> " + binding.getValue());
        }
        return inj;
    }

    protected static Properties getJNDIConnectionProperties(String dataSrcName) {
        Properties myBatisProperties = new Properties();
        myBatisProperties.setProperty("mybatis.environment.id", "production");
        myBatisProperties.setProperty("jndi.initialContext", "java:comp/env");
        myBatisProperties.setProperty("jndi.dataSource", "jdbc/"+dataSrcName);
        return myBatisProperties;
    }       

    protected static Properties getJDBCConnectionProperties(String dbName) {
        Properties myBatisProperties = new Properties();
        myBatisProperties.setProperty("mybatis.environment.id", "production");
        myBatisProperties.setProperty("JDBC.host", "TrumpetDB.trumpetinc.local");
        // myBatisProperties.setProperty("JDBC.port", "1433");
        myBatisProperties.setProperty("JDBC.schema", dbName);
        myBatisProperties.setProperty("JDBC.username", "username_removed");
        myBatisProperties.setProperty("JDBC.password", "password_removed");
        // myBatisProperties.setProperty("JDBC.autoCommit", "false;Trusted_Connection=False");
        myBatisProperties.setProperty("sqlserver.domain", "trumpetinc");

        return myBatisProperties;
    }       


    protected Filter createTransactionFilter() {
        return new Filter() {
            @Override 
            public void init(FilterConfig fConfig) throws ServletException {
                // TODO Auto-generated method stub
            }

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


            @Override 
            public void doFilter(ServletRequest request,  ServletResponse response, FilterChain chain)
                   throws IOException, ServletException
            {
                HttpServletRequest httpRequest = (HttpServletRequest) request;
                GoldMineService gmSvc;
                ZipCodeTimeZoneLookupService timeZoneLookup;

                // pass the request along the filter chain
                chain.doFilter(request, response);

                // TODO - need to clean up and handle exceptions better.
            }

        };
    }   

}

AppListener module configured with direct JDBC:

package com.trumpetinc.environment;

import static com.google.inject.name.Names.bindProperties;

import java.io.IOException;
import java.util.Map.Entry;
import java.util.Properties;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import com.google.inject.Binding;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;

import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.apache.log4j.Logger;
import org.mybatis.guice.MyBatisModule;
import org.mybatis.guice.datasource.builtin.JndiDataSourceProvider;
import org.mybatis.guice.datasource.builtin.PooledDataSourceProvider;
import org.mybatis.guice.datasource.helper.JdbcHelper;

import com.google.inject.PrivateModule;
import com.google.inject.name.Names;
import com.google.inject.servlet.GuiceServletContextListener;
import com.google.inject.servlet.ServletModule;
import com.trumpetinc.goldmine.GoldMineMapper;
import com.trumpetinc.goldmine.GoldMineService;
import com.trumpetinc.goldmine.GoldMineServiceImplMyBatis;
import com.trumpetinc.livelookup.TimeZoneMapper;
import com.trumpetinc.timezone.TimeZoneLookupServlet;
import com.trumpetinc.timezone.ZipCodeTimeZoneLookupService;
import com.trumpetinc.timezone.ZipCodeTimeZoneLookupServiceImpl;

/**
 * Application Lifecycle Listener implementation class AppListener
 *
 */
// public class AppListener extends GuiceServletContextListener implements ServletContextListener, ServletContextAttributeListener, HttpSessionListener, HttpSessionAttributeListener, HttpSessionActivationListener, HttpSessionBindingListener, ServletRequestListener, ServletRequestAttributeListener
public class AppListener extends GuiceServletContextListener {

    private static final Logger log = Logger
        .getLogger(TimeZoneLookupServlet.class);    

    /**
     * @see GuiceServletContextListener#GuiceServletContextListener()
     */
    public AppListener() {
        super();
        // TODO Auto-generated constructor stub
    }

    @Override
    protected Injector getInjector() {
        ServletModule sm1 =             
            new ServletModule() {
                @Override
                protected void configureServlets() {
                    filter("/livelookup/goldmine2").through(createTransactionFilter());
                    serve("/livelookup/goldmine2").with(com.trumpetinc.livelookup.GoldmineLiveLookupServlet2.class);
                    filter("/upload").through(createTransactionFilter());
                    serve("/upload").with(com.trumpetinc.uploads.HandleUploadRequest.class);
                    filter("/timezonelookup").through(createTransactionFilter());
                    serve("/timezonelookup").with(com.trumpetinc.timezone.TimeZoneLookupServlet.class);
                }
            };
        PrivateModule pm1 = 
            new PrivateModule() {
                @Override
                protected void configure() {
                    install(new MyBatisModule() {
                        @Override
                        protected void initialize() {
                            install(JdbcHelper.SQL_Server_jTDS);
                            // bindDataSourceProviderType(JndiDataSourceProvider.class);
                            bindDataSourceProviderType(PooledDataSourceProvider.class);
                            bindTransactionFactoryType(JdbcTransactionFactory.class);
                            addMapperClass(GoldMineMapper.class);
                            // bindProperties(binder(),getJNDIConnectionProperties("TrumpetGM"));
                        }
                    });
                    // Names.bindProperties(this.binder(),getJNDIConnectionProperties("TrumpetGM"));
                    Names.bindProperties(this.binder(),getJDBCConnectionProperties("GoldMineTpt"));
                    bind(GoldMineServiceImplMyBatis.class);
                    bind(GoldMineService.class).to(GoldMineServiceImplMyBatis.class);
                    expose(GoldMineMapper.class);
                    expose(GoldMineService.class);
                    expose(GoldMineServiceImplMyBatis.class);
                }
            };
        PrivateModule pm2 =
            new PrivateModule() {
                @Override
                protected void configure() {
                    install(new MyBatisModule() {
                        @Override
                        protected void initialize() {
                            install(JdbcHelper.SQL_Server_jTDS);
                            // bindDataSourceProviderType(JndiDataSourceProvider.class);
                            bindDataSourceProviderType(PooledDataSourceProvider.class);
                            bindTransactionFactoryType(JdbcTransactionFactory.class);
                            addMapperClass(TimeZoneMapper.class);
                            // bindProperties(binder(),getJNDIConnectionProperties("TimeZoneLookup"));
                        }
                    });
                    // Names.bindProperties(this.binder(),getJNDIConnectionProperties("TimeZoneLookup"));
                    Names.bindProperties(this.binder(),getJDBCConnectionProperties("TimeZoneLookup"));
                    bind(ZipCodeTimeZoneLookupServiceImpl.class);
                    bind(ZipCodeTimeZoneLookupService.class).to(ZipCodeTimeZoneLookupServiceImpl.class);
                    expose(TimeZoneMapper.class);
                    expose(ZipCodeTimeZoneLookupService.class);
                    expose(ZipCodeTimeZoneLookupServiceImpl.class);
                }
            };

        log.debug("sm1="+sm1);
        log.debug("pm1="+pm1);
        log.debug("pm2="+pm2);

        Injector inj = Guice.createInjector(sm1,pm1, pm2 );
        for (Entry<Key<?>, Binding<?>> binding : inj.getBindings().entrySet() ) {
            log.debug(binding.getKey() + " -> " + binding.getValue());
        }
        return inj;
    }

    protected static Properties getJNDIConnectionProperties(String dataSrcName) {
        Properties myBatisProperties = new Properties();
        myBatisProperties.setProperty("mybatis.environment.id", "production");
        myBatisProperties.setProperty("jndi.initialContext", "java:comp/env");
        myBatisProperties.setProperty("jndi.dataSource", "jdbc/"+dataSrcName);
        return myBatisProperties;
    }       

    protected static Properties getJDBCConnectionProperties(String dbName) {
        Properties myBatisProperties = new Properties();
        myBatisProperties.setProperty("mybatis.environment.id", "production");
        myBatisProperties.setProperty("JDBC.host", "TrumpetDB.trumpetinc.local");
        // myBatisProperties.setProperty("JDBC.port", "1433");
        myBatisProperties.setProperty("JDBC.schema", dbName);
        myBatisProperties.setProperty("JDBC.username", "username_removed");
        myBatisProperties.setProperty("JDBC.password", "password_removed");
        // myBatisProperties.setProperty("JDBC.autoCommit", "false;Trusted_Connection=False");
        myBatisProperties.setProperty("sqlserver.domain", "trumpetinc");

        return myBatisProperties;
    }       


    protected Filter createTransactionFilter() {
        return new Filter() {
            @Override 
            public void init(FilterConfig fConfig) throws ServletException {
                // TODO Auto-generated method stub
            }

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


            @Override 
            public void doFilter(ServletRequest request,  ServletResponse response, FilterChain chain)
                   throws IOException, ServletException
            {
                HttpServletRequest httpRequest = (HttpServletRequest) request;
                GoldMineService gmSvc;
                ZipCodeTimeZoneLookupService timeZoneLookup;

                // pass the request along the filter chain
                chain.doFilter(request, response);

                // TODO - need to clean up and handle exceptions better.
            }

        };
    }   

}

Setting Configuration properties not directly supported by ConfigurationProvider?

The Configuration instance is created in org.mybatis.guice.configuration.ConfigurationProvider.get().

In this method the various named properties found at the top of the class are used to setup the Configuration instance.

These properties only cover a subset of those supported by Configuration, setDefaultStatementTimeout(Integer) and various others are not covered.

And the current ordering of things means there's no opportunity to modify the Configuration instance before the mapped statements are built.

E.g. here we can see getDefaultStatementTimeout() is called as part of creating the mapped statement (see top of stack) and this is triggered as part of creating the Configuration (see bottom of stack):

Configuration.getDefaultStatementTimeout()
MappedStatement$Builder.<init>(Configuration, ...
MapperBuilderAssistant.addMappedStatement(...
XMLStatementBuilder.parseStatementNode()
XMLMapperBuilder.buildStatementFromContext(List<XNode>, String)
XMLMapperBuilder.buildStatementFromContext(List<XNode>)
XMLMapperBuilder.configurationElement(XNode)
XMLMapperBuilder.parse()
MapperAnnotationBuilder.loadXmlResource()
MapperAnnotationBuilder.parse()
MapperRegistry.addMapper(Class<T>)
Configuration.addMapper(Class<T>)
ConfigurationProvider.get()
ConfigurationProvider.get()
BoundProviderFactory<T>(ProviderInternalFactory<T>).provision(...

So there's no possibility to set things like the default statement timeout inbetween the creation of the Configuration and their use in creating mapped statements.

At the moment it looks like the only solution to setting unsupported properties is to generate a pull request (involving a new named property in ConfigurationProvider) and then wait for a new release.

Is this correct?

I want to use another SqlSession

Mybatis-Guice uses DefaultSqlSession as the implementation of SqlSession currently.
but I want to use another one.
Is it possible to modify as follows:

currently MyBatisModule

    @Override
    final void internalConfigure() {
        ...
        bind(SqlSessionFactory.class).toProvider(SqlSessionFactoryProvider.class).in(Scopes.SINGLETON);
        ...
    }

modified MyBatisModule

    @Override
    final void internalConfigure() {
        ...
        bindSqlSession();
        ...
    }

    protected void bindSqlSession() {
        bind(SqlSessionFactory.class).toProvider(SqlSessionFactoryProvider.class).in(Scopes.SINGLETON);
    }

Problems with 3.10 on useConfigurationProvider

Hi,
On the last version useConfigurationProvider don't work correctly.

public static void main(String[] args) {
        Injector injector = Guice.createInjector(new MyBatisModule() {
            @Override
            protected void initialize() {
                install(JdbcHelper.HSQLDB_IN_MEMORY_NAMED);
                Names.bindProperties(binder(), createTestProperties());

                useConfigurationProvider(MyConfigurationProvider.class);
                bindDataSourceProviderType(PooledDataSourceProvider.class);
                bindTransactionFactoryType(JdbcTransactionFactory.class);

                lazyLoadingEnabled(true);
            }

            private Properties createTestProperties() {
                Properties myBatisProperties = new Properties();
                myBatisProperties.setProperty("mybatis.environment.id", "test");
                myBatisProperties.setProperty("JDBC.schema", "mybatis-guice_TEST");
                myBatisProperties.setProperty("JDBC.username", "sa");
                myBatisProperties.setProperty("JDBC.password", "");
                myBatisProperties.setProperty("JDBC.autoCommit", "false");
                return myBatisProperties;
            }
        });

        Configuration configuration = injector.getInstance(Configuration.class);
        System.out.println(configuration.isLazyLoadingEnabled());
    }

    public static class MyConfigurationProvider extends ConfigurationProvider {

        @Inject
        public MyConfigurationProvider(Environment environment) {
            super(environment);
        }

    }

In example : console output => LazyLoadingEnabled = false.
If comment line : useConfigurationProvider(MyConfigurationProvider.class);
Console output => LazyLoadingEnabled = true.

The problems is because this.bindListener(KeyMatcher.create(Key.get(ConfigurationProvider.class)), ...
Matcher match only ConfigurationProvider and not MyConfigurationProvider because equals test.

2 solutions :

  1. Change KeyMatcher
public boolean matches(Binding<?> t) {
    return this.key.getTypeLiteral().getRawType().isAssignableFrom(t.getKey().getTypeLiteral().getRawType());
 }
  1. Or change MyBatisModule, remove useConfigurationProvider and add constructor
private final Key<? extends ConfigurationProvider> configurationProviderKey;

public MyBatisModule() {
   this(ConfigurationProvider.class);
}

public MyBatisModule(Class<? extends ConfigurationProvider> configurationProviderClass) {
   this.configurationProviderKey = Key.get(configurationProviderClass);
}
...
final void internalConfigure() {
...
        this.bind(Configuration.class).toProvider(this.configurationProviderKey).in(Scopes.SINGLETON);
...
}
...
protected final void bindConfigurationSetting(ConfigurationSetting configurationSetting) {
        this.bindListener(KeyMatcher.create(configurationProviderKey), new ProvisionListener[]{ConfigurationProviderProvisionListener.create(configurationSetting)});
    }

    protected final <P extends Provider<? extends ConfigurationSetting>> void bindConfigurationSettingProvider(P configurationSettingProvider) {
        this.bindListener(KeyMatcher.create(configurationProviderKey), new ProvisionListener[]{ConfigurationProviderProvisionListener.create(configurationSettingProvider, this.binder())});
    }
...
protected final void addMapperClass(Class<?> mapperClass) {
        Preconditions.checkArgument(mapperClass != null, "Parameter 'mapperClass' must not be null");
        this.bindListener(KeyMatcher.create(configurationProviderKey), new ProvisionListener[]{ConfigurationProviderProvisionListener.create(new MapperConfigurationSetting(mapperClass))});
        this.bindMapper(mapperClass);
    }
...

What do you think ?

Set custom driver property

Hello,

I need to set a driver property using Names.bindProperties(binder(), properties);
The JDBC connection property is settable in JDBC with properties.setProperty("foreign_keys", "true"); but I didn't manage to do it with MyBatis. Can you please explain me how can I do it?

Thy in advance!

Lucien

Add Tx Transaction interceptor

In a local version of the project, I added support for JTA TransactionManager.

Borrowed the description of the rules of the transaction JavaEE 7
javax.transaction.Transactional.TxType.
My main project is working on the JVM 1.6. In Java 6 no @transactional.

Took two objects from the project Apache Aries transaction-jdbc.

  • TransactionToken
  • TransactionAttribute.

To work with TransactionManager must register this object

TransactionManager manager;

install(new MyBatisModule(){
    @Override
    protected void initialize() {
        if(manager != null)
            bind(TransactionManager.class).toInstance(manager);
    }
});

Transactional annotation processing consistently put two handlers.
The first handler TxTransactionalMethodInterceptor.
The second handler TransactionalMethodInterceptor.

TxTransactionalMethodInterceptor receives main object Guice

@Inject Injector injector;

Requests the presence of a registered provider object TransactionManager.
If the object is not registered, transfers control parameter invocation.
If the object is registered

  • The objects are mapped TxType it TransactionAttribute.
  • Start process of initiating a transaction.
  • Transfer control parameter invocation.
  • If an error signal TransactionManager set rollbackOnly.
  • Ends the transaction (commit or rollback).

Change: https://gist.github.com/alexey-su/567495a9d29b0d175b7c

Adding enforced format.xml

@christianpoitras I've been adding to the various projects format.xml which is in mybatis-parent now. This enforces 2 character spacing for mybatis. This has been an easy win for smaller projects at this point. I was thinking about possibly bringing it in here given checkstyle complaints over 3k. It won't fix all those issues but will knock off a good number. Because this is such a noisy change in general the first time, I wanted to raise the question here letting you decide if it is worth doing. There are no outstanding PR so if anytime was a good time, now is.

JNDI DataSource doesn't allow configure env parameters

There is a need to configure additional env parameters to initilize JNDI context.

It least following update will be cool to have:

public class WLJndiDataSourceProvider implements Provider<DataSource> {

    /**
     *
     */
    private final Properties properties = new Properties();

    /**
     *
     *
     * @param initialContext
     */
    @com.google.inject.Inject(optional = true)
    public void setInitialContext(@Named("jndi.initialContext") final String initialContext) {
        properties.setProperty(JndiDataSourceFactory.INITIAL_CONTEXT, initialContext);
    }

    /**
     *
     *
     * @param dataSource
     */
    @com.google.inject.Inject(optional = true)
    public void setDataSource(@Named("jndi.dataSource") final String dataSource) {
        properties.setProperty(JndiDataSourceFactory.DATA_SOURCE, dataSource);
    }

    @com.google.inject.Inject(optional = true)
    public void setEnvInitialContextFactory(@Named("java.naming.factory.initial") final String intialFactory) {
        properties.setProperty(JndiDataSourceFactory.ENV_PREFIX+Context.INITIAL_CONTEXT_FACTORY, intialFactory);
    }

    @com.google.inject.Inject(optional = true)
    public void setEnvProviderUrl(@Named("java.naming.provider.url") final String providerUrl) {
        properties.setProperty(JndiDataSourceFactory.ENV_PREFIX+Context.PROVIDER_URL, providerUrl);
    }

    /**
     * {@inheritDoc}
     */
    public DataSource get() {
        JndiDataSourceFactory factory = new JndiDataSourceFactory();
        factory.setProperties(properties);
        return factory.getDataSource();
    }

}

HashMap concurrent modify error

The large number of threads an error described in http://stackoverflow.com/questions/29967401/strange-hashmap-exception-hashmapnode-cannot-be-cast-to-hashmaptreenode

In class XASqlSessionManager change from
private static HashMap<GlobalKey, GlobalToken> globalTokens = new HashMap<XASqlSessionManager.GlobalKey, XASqlSessionManager.GlobalToken>();
to
private static Map<GlobalKey, GlobalToken> globalTokens = new ConcurrentHashMap<XASqlSessionManager.GlobalKey, XASqlSessionManager.GlobalToken>();

Guice throws CreationException when adding the same type handler in the Modules

As of the 3.7.0 version of mybatis-guice type handlers are bound using a provider instance instead of a provider class. This creates a subtle difference where type handlers cannot be added to multiple modules in the same injector.

The fix is super easy. Guice allows multiple bindings when the provided instances are equal. Can you please override equals (and hashCode) as you see fit for TypeHandlerProvider and possibly MapperProvider.

see TechniqueSoftware@0d2c80b

Thanks

Support Guice 4.0

Embedding mybatis-guice (latest version) in a project using Guice 4.0 results in the following run time error:

java.lang.NoClassDefFoundError: com/google/inject/internal/util/$Preconditions
    at org.mybatis.guice.MyBatisModule.internalConfigure(MyBatisModule.java:84)
    at org.mybatis.guice.AbstractMyBatisModule.configure(AbstractMyBatisModule.java:59)
    at com.google.inject.AbstractModule.configure(AbstractModule.java:62)
    at com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:340)
    at com.google.inject.spi.Elements.getElements(Elements.java:110)
    at com.google.inject.internal.InjectorShell$Builder.build(InjectorShell.java:138)
    at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:104)
    at com.google.inject.Guice.createInjector(Guice.java:96)

Maybe just relying on the Preconditions class from Guava instead of this internal copy would resolve the issue "smoothly"?

Error in Travis with contact created field

Unit tests runned by Travis fails because of Contact's created field.
Expected Contact [firstName=John, id=1, lastName=Doe, created= 1380031853889, address=null] but found Contact [firstName=John, id=1, lastName=Doe, created= 1380031853890, address=null]

The problem is probably due to the conversion from Long to Timestamp when inserting contact in CleanDatabaseRule.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.