I've developed a JAX-RS JSON API in Wildfly/RESTeasy with a JPA/Hibernate backend and I have serious database access problems.
For example, suddenly the application stop responding and the logs show a bunch of:
ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (EJB default - 4) IJ031012: Unable to obtain lock in 60 seconds: org.jboss.jca.adapters.jdbc.local.LocalManagedConnection
INFO [org.jboss.jca.core.connectionmanager.listener.TxConnectionListener] IJ000302: Unregistered handle that was not registered: org.jboss.jca.adapters.jdbc.jdk7.WrappedConnectionJDK7
WARN [org.jboss.jca.core.connectionmanager.pool.strategy.OnePool] IJ000609: Attempt to return connection twice: org.jboss.jca.core.connectionmanager.listener.TxConnectionListener
WARN [org.jboss.jca.adapters.jdbc.local.LocalManagedConnectionFactory] (default task-9) IJ030020: Detected queued threads during cleanup
ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (ForkJoinPool.commonPool-worker-0) IJ031041: Connection handle has been closed and is unusable
ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (ForkJoinPool.commonPool-worker-1) IJ031050: The result set is closed
I think this is due to multiple access by different users (say 15, 20 users simultaneously), since with one/two users this not happens.
I'm on Hibernate 5.1 and Wildfly 10, and SQL Server 2014. It is a vanilla installation, with no tweaks or custom configurations. How can I fine-tune the infrastructure to avoid these issues?
The problem was related to the REST services being #Stateless and therefore opening transactions on each request. The solution was to inject #Stateless DAOs into the REST services: no more locking issues.
Use HikariCP connection pool.
Based on your traffic configure no of connections in the connection pool as well as in database.
In the connection pool there is option to maintain some amount connections available all the time. And also set the connection isolation type as after commit only.
Below is the sample of it,
<persistence-unit name="sample" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<!-- provider -->
<property name="hibernate.connection.provider_class" value="com.xo.web.persistence.XOHikariCPConnectionProvider"/>
<!-- Hibernate properties -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.archive.autodetection" value="hbm" />
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="show_sql" value="false"/>
<property name="hibernate.connection.release_mode" value="after_transaction"/>
<property name="hibernate.connection.autocommit" value="false"/>
<property name="hibernate.connection.isolation" value="2"/>
<property name="hibernate.ejb.interceptor" value="com.xo.web.persistence.intercept.XoEntityInterceptor"/>
<property name="hibernate.jdbc.batch_size" value="100"/>
<property name="hibernate.order_inserts" value="true"/>
<property name="hibernate.order_updates" value="true"/>
<!-- Hikari settings -->
<property name="maximumPoolSize" value="80" />
<property name="autoCommit" value="false" />
<property name="minimumPoolSize" value="20" />
<property name="idleTimeout" value="60000" />
<property name="maxLifetime" value="600000" />
<property name="connectionInitSql" value="select 1" />
<property name="connectionTimeout" value="1000" />
<property name="validationTimeout" value="1000" />
<property name="cachePrepStmts" value="true" />
<property name="prepStmtCacheSize" value="250" />
<property name="prepStmtCacheSqlLimit" value="2048" />
</properties>
</persistence-unit>
Related
I have a question.I am integrating EJB, JAX-RS, CDI, JPA, and data sources. When I integrate these into wildfly-swarm, there are some problems that can not work properly.
yaml.xml:
datasources:
jdbc-drivers:
com.mysql:
driver-class-name: com.mysql.jdbc.Driver
xa-datasource-class-name: com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
driver-module-name: com.mysql
data-sources:
PicketlinkDS:
driver-name: com.mysql
connection-url: jdbc:mysql://localhost:3306/testjpa
user-name: root
password: javacom2
jta : true
use-java-context: true
min-pool-size : 8
max-pool-size : 20
pool-prefill : true
connection-checker-class-name : org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker
background-validation : true
exception-sorter-class-name : org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter
connection-properties : CharacterEncoding/ UTF-8 UseUnicode/true
persistence.xml:
<persistence-unit name="picketlink" transaction-type="JTA">
<jta-data-source>java:jboss/datasources/PicketlinkDS
</jta-data-source>
<!-- 声明是否扫描jar文件中标注了#Enity类加入到上下文.若不扫描,则如下:(可选) -->
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.query.substitutions" value="true=1, false=0" />
<property name="hibernate.dialect.storage_enginet"
value="innodb" />
<!-- JBoss/Wildfly JTA Transaction -->
<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
<property name="hibernate.cache.use_query_cache" value="false" />
<property name="hibernate.cache.use_second_level_cache"
value="false" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.hbm2ddl.import_files" value="initial_data.sql" />
<property name="hibernate.jdbc.batch_size" value="1000" />
<property name="hibernate.order_inserts" value="true" />
<property name="hibernate.order_updates" value="true" />
<property name="hibernate.connection.characterEncoding"
value="UTF-8" />
<property name="hibernate.current_session_context_class"
value="jta" />
<property name="wildfly.jpa.default-unit" value="true" />
</properties>
</persistence-unit>
main Class:
ClassLoader cl = Main.class.getClassLoader();
URL stageConfig = cl.getResource("project-development.yml");
Swarm swarm = new Swarm().withConfig(stageConfig);
// Create one or more deployments
JAXRSArchive deployment = ShrinkWrap.create(JAXRSArchive.class);
deployment.addAsWebInfResource(new ClassLoaderAsset("META-INF/persistence.xml", Main.class.getClassLoader()), "classes/META-INF/persistence.xml");
// Add resource to deployment
//deployment.addClass(PmsPersonService.class);
deployment.addClass(Person.class);
// deployment.addClass(EntityManagerProvider.class);
deployment.addAsWebInfResource(new ClassLoaderAsset("META-INF/load.sql", Main.class.getClassLoader()), "classes/META-INF/load.sql");
deployment.addResource(RestApplication.class);
deployment.addResource(HelloWorldEndpoint.class);
deployment.addAllDependencies();
swarm.start();
swarm.deploy(deployment);
exception:
"WFLYCTL0412: Required services that are not installed:" =>"jboss.naming.context.java.jboss.datasources.PicketlinkDS"],
idea ,Run on how to deal with this exception?
Very anxious!!!!!!!!
First off I'd suggest removing the custom main() as there's nothing specific you're doing there that can't be achieved with Maven war packaging.
Secondly, I think your yaml is missing the swarm: as the first level, and you can also remove the JDBC Driver creation and let WF Swarm do that for you. For that I switched the driver-name to mysql, which will work so long as the JDBC driver dependency for MySQL is part of the project.
swarm:
datasources:
data-sources:
PicketlinkDS:
driver-name: mysql
connection-url: jdbc:mysql://localhost:3306/testjpa
user-name: root
password: javacom2
jta: true
use-java-context: true
min-pool-size: 8
max-pool-size: 20
pool-prefill: true
connection-checker-class-name: org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker
background-validation: true
exception-sorter-class-name: org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter
connection-properties: CharacterEncoding/ UTF-8 UseUnicode/true
I'm experiencing a weird behaviour with our Java web application, configured to access a PostgreSQL database through C3p0 ComboPooledDataSource.
First of all, PostgreSQL server installation has default parameters, we didn't need to change any variable in it..
We run our queries using Spring JdbcTemplate, version 3.2.12.RELEASE. As it is for PostgreSQL, it is configured with default parameters.
Here it is our context configuration with C3p0 and Spring;
<bean id="resoilDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<!-- access configuration -->
<property name="driverClass" value="org.postgresql.Driver" />
<property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/*****" />
<property name="user" value="******" />
<property name="password" value="******" />
<!-- pool sizing -->
<property name="initialPoolSize" value="1" />
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="6" />
<property name="acquireIncrement" value="3" />
<property name="maxStatements" value="150" />
<!-- refreshing connections -->
<property name="maxIdleTime" value="180" /> <!-- 3min -->
<property name="maxIdleTimeExcessConnections" value="120" /> <!-- 3min -->
<!-- timeouts e testing -->
<property name="idleConnectionTestPeriod" value="120" /> <!-- 60 -->
<property name="testConnectionOnCheckout" value="true" />
<property name="testConnectionOnCheckin" value="false" />
<property name="preferredTestQuery" value="SELECT 1" />
</bean>
<bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="resoilDataSource"></property>
</bean>
Let me describe the problem we are encountering:
once we reach "maxPoolSize" of idle connections opened on Postgres side, this connections never expires, they remain in "idle" state and there's no way C3p0 will get any of them back for pooling..
I would expect that once one of these opened connections excess idle time, C3p0 is able to reuse it due to the "maxIdleTimeExcessConnections" parameter.
Unfortunately, this never happens.
I also tried to substitute C3p0 ComboPooledDataSource with Apache DBCP BasicDataSource, but nothing changed.
Before using PostgreSQL database for our application, our customers asked us to install our application integrating other popular databases instead of PostgreSQL (SQL Server and Oracle in particular) and we never experienced this behaviour.
Any ideas about what's going on it's truly appreciated, thanks in advance.
I'm trying to use hibernate jpa and hikaricp for the CP.
But I have an issue that I dont understand, so either my config is bad ... or I do have something else.
this is the config In have in my persistence.xml file :
<properties>
<!-- SQL -->
<property name="hibernate.dialect" value="org.hibernate.spatial.dialect.mysql.MySQLSpatialDialect" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
<!-- HikariCP -->
<property name="hibernate.connection.provider_class" value="com.zaxxer.hikari.hibernate.HikariConnectionProvider"/>
<property name="hibernate.hikari.driverClassName" value="com.mysql.jdbc.Driver" />
<property name="hibernate.hikari.minimumIdle" value="5"/>
<property name="hibernate.hikari.maximumPoolSize" value="30"/>
<property name="hibernate.hikari.maxLifetime" value="150000"/>
<property name="hibernate.hikari.dataSource.user" value="user" />
<property name="hibernate.hikari.dataSource.password" value="password" />
<property name="hibernate.hikari.jdbcUrl"
value="jdbc:mysql://server:3306" />
</properties>
Still I'm having 100+ connections on the database. I thought that using maximumPoolSize it would have limit my number of connections. Is my configuration OK, based on my research it seems ok to me, but before trying to debug elsewhere I want to make sure it is.
Thanks
You must be missing the hibernate-hikari module jar on your classpath. This module is necessary to integrate hibernate with HikariCP
Here is the official documentation
I have a Java SE 1.7 standalone application.
It uses Hibernate 4.3 final and JPA 2.1 to retrieve thousands of rows from a db2 zos database.
I have a multiple tables tor retrieve related rows from.
All I am testing currently is retrieving the Parent Table rows then two related children table rows.
One child table has a one to one relationship the other has a One to Many relationship.
I can retrieve 2000+ rows from the main parent table OK, I hold these rows in a an ArrayList
Then I attempt to retrieve the children table rows using the Ids held in my array list.
This is when I generate the following exception:-
***** Out of Package Error Occurred (2015-01-14 15:55:29.935) *****
Concurrently open statements:
1. SQL string: SELECT .....
Number of statements: 1150
********************
My JPA entity classes do not have any Mappings between them e.g. #ManyTo or #OneTo
Heres my persistence.xml file
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="persistence" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>table.class.One</class>
<class>table.class.Two</class>
<class>table.class.Three</class>
<properties>
<!-- Configuring JDBC properties -->
<property name="javax.persistence.jdbc.url"
value="jdbc:db2://host:port/LOCATION:retrieveMessagesFromServerOnGetMessage=true;emulateParameterMetaDataForZCalls=1;" />
<property name="javax.persistence.jdbc.user" value="user" />
<property name="javax.persistence.jdbc.password" value="pword" />
<property name="javax.persistence.jdbc.driver" value="com.ibm.db2.jcc.DB2Driver" />
<property name="hibernate.default_schema" value="schema" />
<property name="hibernate.connection.autocommit" value="false" />
<!-- Hibernate properties -->
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.dialect" value="org.hibernate.dialect.DB2390Dialect" />
<property name="hibernate.connection.provider_class"
value="org.hibernate.connection.C3P0ConnectionProvider" />
<!-- Configuring Connection Pool -->
<property name="hibernate.c3p0.min_size" value="5" />
<property name="hibernate.c3p0.max_size" value="20" />
<property name="hibernate.c3p0.timeout" value="500" />
<property name="hibernate.c3p0.max_statements" value="50" />
<property name="hibernate.c3p0.maxStatementsPerConnection"
value="10" />
<property name="hibernate.c3p0.idle_test_period" value="2000" />
<property name="hibernate.c3p0.testConnectionOnCheckout"
value="true" />
<property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces"
value="true" />
</properties>
</persistence-unit>
</persistence>
How can I get JPA and/or hibernate to "close" the open statements?
Is it possible to make JPA use SSL for it's connections. I don't know very much about JPA, so I can't provide many details about what version and provider I'm using, but here is a stripped version of my persistence.xml file. Is there a property you can add that makes it use secure connections?
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="MY_PERSISTENCE_UNIT" transaction-type="RESOURCE_LOCAL">
<!-- declare class entities here -->
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://URL_TO_SERVER" />
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.user" value="USERNAME" />
<property name="javax.persistence.jdbc.password" value="PASSWORD" />
<!-- Optimize database writes to use batching. -->
<property name="eclipselink.jdbc.batch-writing" value="JDBC" />
<!-- Avoids flush being triggered before every query execution. -->
<property name="eclipselink.persistence-context.flush-mode"
value="COMMIT" />
<!-- Configure connection pool. -->
<property name="eclipselink.jdbc.connections.initial" value="1" />
<property name="eclipselink.jdbc.connections.min" value="64" />
<property name="eclipselink.jdbc.connections.max" value="64" />
<!-- Timeout for connection. -->
<property name="eclipselink.jdbc.timeout" value="10" />
<!-- Configure cache size. -->
<property name="eclipselink.cache.size.default" value="1000" />
<!-- Configure database to be created on startup if not already existing.-->
<property name="eclipselink.ddl-generation" value="create-tables" />
<!-- Configure simple SQL logging for demonstration. -->
<property name="eclipselink.logging.level" value="FINE" />
<property name="eclipselink.logging.thread" value="false" />
<property name="eclipselink.logging.session" value="false" />
<property name="eclipselink.logging.exceptions" value="false" />
<property name="eclipselink.logging.timestamp" value="false" />
</properties>
</persistence-unit>
It is not anything JPA specific, just about adding arguments to JDBC connection String. Assuming that everything else is correctly set, then adding this should be enough:
?useSSL=true&requireSSL=true
If SSL connection in general is not working, then this page provides more information: MySQL 20.3.4.5. Connecting Securely Using SSL
I found this was useful in EclipseLink 2.5.0 to pass properties through to the JDBC driver:
<property name="eclipselink.jdbc.property.my_property_name" value="my_value" />
This is driver specific, but in your case it would be:
<property name="eclipselink.jdbc.property.useSSL" value="true" />
<property name="eclipselink.jdbc.property.requireSSL" value="true" />