PaolaG
PaolaG

Reputation: 814

JDBC connection lost during task in Tomcat Server

MY STRUCTURE:

All my webApps are developed in Spring Boot, with Java 8.

CASE:
In one of the specified application (called B) I call an API of A. This API open a connection with the SQL Server, for read an entry and send to B the value of reading entry.

I test it with A and B running in my local machine, and A official and B local.

In test I don't have any problem, the API works fine.

But when I call this API from official to official, after some seconds I had some errors in log and I lost all the connection to my Databases:

Forwarding to error page from request [/mycontroller/request] due to exception 
[org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5ec9a879 has been closed already]


java.lang.IllegalStateException: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5ec9a879 has been closed already

or:

EntityManager is closed

After this error I can only restart my Tomcat Server to restore the connection with the databases.

This is my code, that called API:

 @Override
            public void apiCalled() {
            try {
                for(Entity c : entityRepository.findEntity()) {
                    String ftt = keycloakRestTemplate.getForEntity(URI.create(mux+"/api/apiCalled?num="+c.getNumber()), String.class).getBody();
                    if(ftt == null) {
                        continue;
                    }
                    FttDto f = new ObjectMapper().readValue(ftt, FttDto.class);

                    c.setNumberF(f.getNumberF());
                    c.setDateF(convertDate(f.getDateF()));
                    commessaRepository.save(c);
                }
            } catch (RestClientException | IOException e) {
                LOG.error("Api Service Get error: {}", e.getMessage());
            }
        }

Code of the API:

@PersistenceContext(unitName="persistenceUnitI24")
private EntityManager emI24;

public FttDto findByNumber(String number) {
    Session session = emI24.unwrap(Session.class);
    FttI24 fttListI24 = (FttI24) session.createQuery("select f from FttRg r join r.idFttI24 f join r.nota n where n.nota like '%"+number+"%'")
     .setCacheMode(CacheMode.IGNORE)
     .uniqueResult();

    if(fttListI24 == null) {
        return null;
    }

    FttDto ftt = new FttDto();
    ftt.setNumberF(fttListI24.getNumberF());
    ftt.setDateF(fttListI24.getDateF());
    return ftt;
}

Any ideas?

EDIT

This is my server.xml for my DBs connection:

        <Resource 
          name="jdbc/schemaA"
          auth="Container" 
          factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
          type="javax.sql.DataSource"
          initialSize="2"
          maxActive="4"
          maxIdle="2" 
          minIdle="1" 
          username="user" 
          password="password" 
          driverClassName="net.sourceforge.jtds.jdbc.Driver" 
          url="jdbc:jtds:sqlserver://sqlServer_ip/schemaA" 
          testOnBorrow="true"
          testWhileIdle="true"
          validationQuery="select 1"
          validationInterval="300000"/>

    <Resource 
          name="jdbc/schemaB"
          auth="Container" 
          factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
          type="javax.sql.DataSource" 
          initialSize="4"
          maxActive="8"
          maxWait="10000"
          maxIdle="8"
          minIdle="4"
          username="userB"
          password="passB" 
          driverClassName="com.mysql.jdbc.Driver" 
          url="jdbc:mysql://mysqlserver_ip/schemaB?zeroDateTimeBehavior=convertToNull" 
          testOnBorrow="true" 
          testWhileIdle="true" 
          validationQuery="select 1"
          validationInterval="300000" />

Adding DataSource Config in spring.

on WebApp B:

@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
@Bean(name = "dataSource")
@ConfigurationProperties(prefix="spring.datasource")
@Primary    
public DataSource dataSource() throws NamingException {

    if(Arrays.asList(environment.getActiveProfiles()).contains("dev")) {
        return new BasicDataSource();
    }else {
        Context ctxConfig = new InitialContext();
        return (DataSource) ctxConfig.lookup("java:comp/env/jdbc/schemaB");
    }
}

@Bean
@Primary
public JpaTransactionManager transactionManager() throws NamingException {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());

    return transactionManager;
}

@Bean
public JpaVendorAdapter jpaVendorAdapter(){

    HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();

    jpaVendorAdapter.setDatabase(Database.MYSQL);
    jpaVendorAdapter.setGenerateDdl(true);
    jpaVendorAdapter.setShowSql(false);
    jpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQLInnoDBDialect");

    return jpaVendorAdapter;
}

@Bean
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException {
    LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();

    entityManagerFactoryBean.setDataSource(dataSource());
    entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter());
    entityManagerFactoryBean.setPackagesToScan("domain.mydomain");
    entityManagerFactoryBean.setPersistenceUnitName("persistenceUnit");

return entityManagerFactoryBean;
}
}

on WebApp A:

 @Configuration
public class DataSourceI24Config {

    @Autowired
    private Environment environment;

    @Bean(name = "dataSourceI24")
    @ConfigurationProperties(prefix = "spring.datasource.i24")
    public DataSource dataSourceI24() throws NamingException {
            Context ctxConfig = new InitialContext();
            return (DataSource) ctxConfig.lookup("java:comp/env/jdbc/schemaA");

    }

    @Bean(name="transactionManagerI24")
    public JpaTransactionManager transactionManagerI24() throws NamingException {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactoryI24().getObject());
        return transactionManager;
    }

    @Bean(name="entityManagerI24")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryI24() throws NamingException {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();

        entityManagerFactoryBean.setDataSource(dataSourceI24());
        entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        entityManagerFactoryBean.setPackagesToScan("appA.i24.domain");
        entityManagerFactoryBean.setPersistenceUnitName("persistenceUnitI24");

       [...]

        return entityManagerFactoryBean;
    }
}

Upvotes: 1

Views: 1315

Answers (1)

Jackkobec
Jackkobec

Reputation: 6705

I had a same problem like this with h2 database. The solution was use db in the multiple connection mode ( more then one possible connection, connection pool).

Upvotes: 1

Related Questions