简体   繁体   中英

JPA component in camel cannot reconnect automatically to database

When I reboot my database while my application is running, JPA components cannot reconnect automatically.

2017-02-09 17:45:08,400 ERROR o.h.e.j.spi.SqlExceptionHelper(131) - Connection closed. - [Camel (camel-1) thread #99 - jpa://com.toto.Toto  ]

But still I am able to execute SQL request with spring-data in my CXF routes.

My datasource definition in context.xml :

<!-- JDBC connection -->
    <Resource name="jdbc/oracle"
            auth="Container"
            type="javax.sql.DataSource"
            username="toto"
            password="toto"
            factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
            driverClassName="oracle.jdbc.driver.OracleDriver"
            url="jdbc:oracle:thin:@toto:1568:SID"
            maxTotal="100"
            maxIdle="10"
            testOnBorrow="true"
            validationQuery="select 1 from dual"/>

And here is what my JPA component looks like :

    @Component
public class TotoPollerRoute extends RouteBuilder {

  private final String uri;

  private static final String POLLING_REQUEST = "select tt from Toto tt where tt.key = 1";

  public TotoPollerRoute() {
    super();
    final StringBuilder uriBuilder = new StringBuilder();
    uriBuilder.append("jpa://");
    uriBuilder.append(TotoPollerRoute.class.getName());
    uriBuilder.append("?");
    uriBuilder.append("consumeDelete=false");
    uriBuilder.append("&consumeLockEntity=true");
    uriBuilder.append("&consumer.SkipLockedEntity=true");
    uriBuilder.append("&maximumResults=10");
    uriBuilder.append("&consumer.query=");
    uriBuilder.append(POLLING_REQUEST);
    this.uri = uriBuilder.toString();
  }

  @Override
  public void configure() {
    // @formatter:off
    from(uri)
        .to("TotoMainRoute");
    // @formatter:on
  }
}

Any idea ?

After some deep debugging I finally figured out my JPA components weren't using the EntityManagerFactory declared in the Spring context.

Two ways to solve that :

  1. Modify the JPA uri on each JPA component and add the sharedEntityManager option :

     private final String uri = "jpa://TotoPollerRoute?consumeDelete=false" + "&consumeLockEntity=true" + "&consumer.SkipLockedEntity=true" + "&maximumResults=10" + "&sharedEntityManager=true" + "&joinTransaction=false" + "&consumer.query=select tt from Toto tt where tt.key = 1"; 
  2. Instanciate JPA component in Spring :

     @Bean public JpaComponent jpa() { final JpaComponent jpa = new JpaComponent(); jpa.setSharedEntityManager(true); jpa.setJoinTransaction(false); return jpa; } 

Try specifying the following attributes

  • validationInternal="30000"
  • testWhileIdle="true"
  • testOnReturn="false"

In addition to the following which you have declared:

  • testOnBorrow="true"
  • validationQuery="select 1 from dual"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM