Second level caching in hibernate while migrating from JBoss to TomEE - java

I need to migrate my application built in GWT from Jboss to tomEE. The application has second level caching enabled in hibernate using Jboss cache. Is it possible to use Jboss cache in tomEE or do I have to find an alternative? If possible, can anyone please help me with the configuration of hibernate.cfg.xml? Below is the configuration
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.sybase.jdbc3.jdc.Sybdriver</property>
<property name="hibernate.connection.url">xyz...</property>
<property name="hibernate.connection.username">xyz..</property>
<property name="hibernate.connection.password">xyz..</property>
<property name="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
<property name="transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property>
<property name="dialect">org.hibernate.dialect.SybaseASE15Dialect</property>
<property name="generate_statistics">false</property>
<property name="jdbc.use_scrollable_resultset">false</property>
<property name="cache.provider_class">org.hibernate.cache.jbc.JBossCacheRegionFactory</property>
<property name="cache.use_second_level_cache">true</property>
<property name="cache.use_minimal_puts">true</property>
<property name="cache.use_structured_entries">true</property>
<property name="cache.use_query_cache">true</property>
<property name="cache.region.factory_class">org.hibernate.cache.jbc2.JndiMultiplexedJBossCacheRegionFactory</property>
<property name="cache.region.jbc2.cachefactory">java:CacheManager</property>
<property name="cache.region.jbc2.cfg.entity">mvcc-entity</property>
<property name="cache.region.jbc2.cfg.collection">mvcc-entity</property>
<property name="cache.region.jbc2.cfg.query">local-query</property>
<mapping resource="book.hbm.xml" />
</session-factory>
</hibernate-configuration>

We cannot achieve the second level caching using JBoss cache in TomEE. We have implemented a similar caching mechanism using Ehcache which is a little slow but works fine.

<property name="cache.region.jbc2.cfg.entity">mvcc-entity</property>
<property name="cache.region.jbc2.cfg.collection">mvcc-entity</property>
<property name="cache.region.jbc2.cfg.query">local-query</property>
We see that entity, collection, and query caching are enabled by using JBoss cache implementation specific to JBoss server. In the case of TomEE, we cannot have the same configuration. You would have to implement a different caching technique using different caching technologies available and match it with the usage of second-level cache(like say read-only, read-write, transactional etc.). In a similar setup, I had used "Ehcache" and that had solved the problem.

Related

Using Ignite for Hibernate 2nd level cache with S3 discovery, changes are not progagated

We have deployed a cluster to AWS configured to use Ignite as a hibernate 2nd level cache, and we're using S3 discovery. On startup we can see the nodes do connect to each other correctly.
However, when a hibernate entity is updated on one server, the change is not propagated through the cluster so other servers continue to have the old value.
Here is a snippet of our ignite config..
```
<!-- Basic configuration for transactional cache. -->
<bean id="transactional-cache" class="org.apache.ignite.configuration.CacheConfiguration" abstract="true">
<property name="cacheMode" value="REPLICATED"/>
<property name="atomicityMode" value="TRANSACTIONAL"/>
<property name="writeSynchronizationMode" value="FULL_ASYNC"/>
<property name="backups" value="0"/>
</bean>
<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration" >
<property name="discoverySpi" ref="discoverySpi"/>
<property name="gridName" value="hibernate-grid"/>
<property name="cacheConfiguration">
<list>
<bean parent="transactional-cache">
<property name="name" value="hibernate.io.milton.vfs.db.Auditable"/>
</bean>
```
The exact same application code, when configured with hazelcast 2nd level cache, does work.
I'm sure there's just something wrong with our config. Can anyone suggest a pointer?
Most likely you hit a known issue with binary format which is used as the default one in Ignite. See the warning callout here for details: https://apacheignite-mix.readme.io/docs/hibernate-l2-cache#l2-cache-configuration
Switching to OptimizedMarshaller should fix the issue.

Should I define datasources in application or in app server?

I've developed applications (running on Jboss server) with two different teams. One team had datasource configuration inside of the application WAR file and another one had it inside of the application server's standalone.xml. And I'm not sure which approach is better.
So, here are some advantages that I've found in defining datasource inside of the server's standalone.xml.
Defining datasource in server's standalone.xml is more secure than in war file. If the database connection credentials stored in the server's standalone.xml, which is almost never modified, it is safer than having the password inside of the war file, which is often transferred from developer's machines to the server and database configuration is spread by all developers computers.
By having datasource in standalone.xml, we can make war file smaller, as JDBC driver could be installed as a module and can be removed from war file. In addition, loading JDBC as module is more efficient as from classpath.
We can put datasource inside of the standalone.xml if we don't want the application development team be aware of database connection settings.
By having datasource configurations in application WAR file, I see the following advantages, which are:
Development team doesn't have permission to change Jboss configuration files in environment where Jboss is running. So DB connection only can be defined in application.
It is useful in development state, when developers often need to switch between different database connections. For example, the developer can specify connection when building a WAR file.
So I'd like to know if there are another advantages in both approaches. And on your opinion which approach is better?
In addition to the points noted in the question, another advantage in having the datasources outside the application is that it allows for using the same war file in different regions. This would allow the team to have different databases for different environments, like Test, Perf and Prod while using the same war file.
You can do a deployment once and then the war file which has been tested by your QA team can be promoted to the production region. This would make sure that no untested code goes into higher regions while avoiding the need for SCM forks and code freezes.
I favour having the datasource exposed by the application server with a caveat..
You need your development team to at least know their way around with your application server or to have at least access to the jboss console to review the configuration or change it..
Reason being that for example they need to monitor the connection usage of the datasource connection pool.. Since you're speaking about jboss, I don't know if the "live" bean for the datasource with jboss AS exposes the same information natively of for example oracle ucp (ucp .getStatistics is a godSend for more than one reason..).
Consider that EVEN if you internalize the datasource in xml, using the concept of profiles you can make some field of the xml being "filled" with some specific value in one or another property file based on the profile the application is loaded with..
e.g with spring you can surely do
<beans profile="local">
<bean id="dataSource" class="oracle.ucp.jdbc.PoolDataSourceFactory" factory-method="getPoolDataSource">
<property name="URL" value="jdbc:oracle:thin:#db00-ccea.labucs.int:1521:CCEA"/>
<property name="user" value="myuser_DCI"/>
<property name="password" value="mypassword_DCI"/>
<property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleConnectionPoolDataSource"/>
<property name="connectionPoolName" value="${name.connection.pool}"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="1000"/>
<property name="maxIdleTime" value="3000"/>
<property name="maxStatements" value="3000"/>
<property name="validateConnectionOnBorrow" value="true" />
<property name="inactiveConnectionTimeout" value="3000" />
<property name="connectionWaitTimeout" value="3000"/>
<property name="abandonedConnectionTimeout" value="3000"/>
<qualifier value ="dataSourceDCI" />
</bean>
<orcl:pooling-datasource id="dataAltSource"
url="jdbc:oracle:thin:#db00-ccea.labucs.int:1521:CCEA" username="some_OWN" password="some_OWN"/>
<util:properties id="flyway.prop" location="classpath:config_local.properties"/>
</beans>
meaning on local profile load the properties from the config_loca.properties file inside the classpath
and have as well
<beans profile="qa">
<bean id="dataSource" class="oracle.ucp.jdbc.PoolDataSourceFactory" factory-method="getPoolDataSource">
<property name="URL" value="jdbc:oracle:thin:#db00-ccea.labucs.int:1521:CCEA"/>
<property name="user" value="myuserQA_DCI"/>
<property name="password" value="myuserQA_DCI"/>
<property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleConnectionPoolDataSource"/>
<property name="connectionPoolName" value="${name.connection.pool}"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="1000"/>
<property name="maxIdleTime" value="3000"/>
<property name="maxStatements" value="3000"/>
<property name="validateConnectionOnBorrow" value="true" />
<property name="inactiveConnectionTimeout" value="3000" />
<property name="connectionWaitTimeout" value="3000"/>
<property name="abandonedConnectionTimeout" value="3000"/>
<qualifier value ="dataSourceDCI" />
</bean>
<bean id="dataAltSource" class="oracle.ucp.jdbc.PoolDataSourceFactory" factory-method="getPoolDataSource">
<property name="URL" value="jdbc:oracle:thin:#db00-ccea.labucs.int:1521:CCEA"/>
<property name="user" value="myuserQA_OWN"/>
<property name="password" value="myuserQA_OWN"/>
<property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleConnectionPoolDataSource"/>
<property name="connectionPoolName" value="${name.connection.pool}"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="1000"/>
<property name="maxIdleTime" value="3000"/>
<property name="maxStatements" value="3000"/>
<property name="validateConnectionOnBorrow" value="true" />
<property name="inactiveConnectionTimeout" value="3000" />
<property name="connectionWaitTimeout" value="3000"/>
<property name="abandonedConnectionTimeout" value="3000"/>
</bean>
<util:properties id="flyway.prop" location="file:///${prefix.iam.dir}/${filecert.iam.path}/external.properties"/>
</beans>
thus in your QA environment or other non-dev environment you instead refer to the external xml file and not to the one integrated in the war..
You can even include username and password to be "filled" via the internal//external properties file to enhance the security if you're concerned.
In order to properly verify your application works, you should try in a staging server before sending it to production.
In that scenario, the war file you install into production, should be the same that you tested, so you shouldn't need to change anything for te application to work in a different environment with different database connections.
So, the database configuration shouldn't be in the war file but in the application server. Additionally, you make the system administrator's live easier because they don't need to manipulate (uncompress and change) your war to install it in a server.
In the very early development live of the application, it can be useful to add the database (and any other development configuration) to reduce the time a developer can put his/her hands on the project and starts programming without having to configure the application in a development application server.
For me, the number one benefit of having all data-source configuration out of the war file is ease of deployment.
If I read your question correctly, you can't ever deploy the exact same build to multiple environments if you include any configuration in the build. A direct implication is you can never deploy you DEV build to QA and more importantly, you can't deploy your QA build to PROD or UAT. This might cause headaches if your process is audited.
If I mis-understood your question, please let me know, otherwise, I hope this helps.

Hibernate Clearing Out Database

I'm running a Hibernate configuration (No JPA) and have inserted a test set using random name generators (for practice with the Criteria API), but on ever startup, hibernate keeps clearing out the test set, forcing me to regenerate it. Is there any way to disable this feature? I'm running only bare-bones (connection and mappings) hibernate configuration.
EDIT (hibernate.cfg.xml):
<property name="hibernate.dialect" >org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url" >jdbc:mysql://localhost:3306/testdb?zeroDateTimeBehavior=convertToNull</property>
<property name="hibernate.connection.username" >Sarah</property>
<property name="hibernate.connection.password"></property>
Ok, so actually adding <property name="hibernate.hbm2ddl.auto">validate</property> seemed to work. I guess hibernate.hbm2ddl.auto must have a default value.

Hibernate and too many connections

I am working on web-project with Hibernate ans Spring MVC.
My hibernate configuration is:
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/xxx</property>
<property name="connection.username">xxx</property>
<property name="connection.password">xxx</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">1800</property>\<property name="hibernate.c3p0.max_statements">50</property>
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="connection.useUnicode">true</property>
<property name="connection.characterEncoding">UTF-8</property>
<property name="current_session_context_class">thread</property>
<property name="show_sql">true</property>
The hibernate sessions are closing in service-classes destructors (these service-classes have DAO objects). But after publishing at production server I've got too many connections exception from mysql.Every server call, the mysql connection was opened. When the connections amount become 101 - db failed. I think that destructors had not time enought for executes so the connections were opened all the time.
Then, I rebuilded the structure. Now, the Spring controllers call the service-class function, that releases the session mannualy. But it doesn't help: the connections are still opened and now I can not use LAZY-collections in views because the session already closed.
How can I solve that problem? What is the usual approach here?
Thank you.

How to avoid stale MySQL/Hibernate connections (MySQLNonTransientConnectionException)

I have a Java webapp using Hibernate and MySQL. If the site isn't used for a few days, the MySQL connection goes stale, and I am met with the following exception:
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
From experience using raw JDBC it is possible to configure the connection to attempt to recover from errors or stale connections, but I don't know how to do this using Hibernate. I am not explicitly calling close() anywhere (but I am betting Hibernate does somewhere deep down in its guts).
Does anybody know what I should do?
What connection pool are you using?
The Hibernate suggestion is not to use the built-in pooling, but use the application server datasource or something like Commons DBCP or C3PO.
I had that problem. Using connection pooling (c3p0) made it go away. It is also a good idea in general to use some connection pooling.
Thanks for the advice. For posterity's sake, I changed the hibernate.cfg.xml from the following:
<property name="connection.url">jdbc:mysql://localhost/FooDB</property>
<property name="connection.username">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.password">secret</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
... to the following:
<property name="connection.datasource">java:/comp/env/jdbc/FooDB</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
This also required adding a standard 'context' entry in my web app's context.xml:
<Resource name="jdbc/FooDB"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root"
password="secret"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/ss?autoReconnect=true" />
We had a similar problem of hibernate mysql connection getting timed out.
So we tried C3P0, with the following configuration:
<property name=c3p0.acquire_increment>1</property>
<property name=c3p0.idle_test_period>3600</property>
<property name=c3p0.max_statements>0</property>
<property name=c3p0.min_size>1</property>
<property name=c3p0.timeout>3605</property>
<property name=hibernate.c3p0.preferredTestQuery>select 1;</property>
Hibernate connection_pool size was set to 1.
This made the timeout problem go away. But we started facing another problem. Long waits.
We have a service (servlet running on jboss), which receives something like 5-6 requests per second. Every request needs to connect to mysql through hibernate. Most of our requests do selects, with an insert/update every 5th-6th request. Normally the request serve time for us is 2-3ms for select and 40-50ms for insert/update. But, after using the above C3P0 configuration, we saw that every request completing after an update was taking almost 4-5 minutes! From our logs, it seemed that randomly a select request will get stuck and will be able to complete only after an update request was received and served.
Above problem goes away if we remove the C3P0 config. Can somebody suggest what we could be doing wrong?
Here is the complete hibernate config for reference:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://xxx.xxx.xxx</property>
<property name="connection.username">xxx</property>
<property name="connection.password">xxx</property>
<property name="connection.pool_size">1</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.cache.use_query_cache">false</property>
<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="show_sql">true</property>
<!-- Transaction isolation 2 = READ_COMMITTED -->
<property name="connection.isolation">2</property>
<property name="connection.autocommit">true</property>
<!-- configuration pool via c3p0-->
<property name="c3p0.acquire_increment">1</property>
<property name="c3p0.idle_test_period">3600</property> <!-- seconds -->
<property name="c3p0.max_size">1</property>
<property name="c3p0.max_statements">0</property>
<property name="c3p0.min_size">1</property>
<property name="c3p0.timeout">3605</property> <!-- seconds -->
<property name="hibernate.c3p0.preferredTestQuery">select 1;</property>
</session-factory>
</hibernate-configuration>
<property name="c3p0.acquire_increment">1</property>
<property name="c3p0.idle_test_period">120</property> <!-- seconds -->
<property name="c3p0.max_size">100</property>
<property name="c3p0.max_statements">0</property>
<property name="c3p0.min_size">10</property>
<property name="c3p0.timeout">180</property> <!-- seconds -->
override these settings on your config file. It ll helps to you.

Categories

Resources