Event listeners on hibernate 5 - java

I'm updating my hibernate from version 3 to 5 and I have in my application context I had the following bean
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"
p:mappingResources="standard.hbm.xml">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
<property name="eventListeners">
<map>
<entry key="merge">
<bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>
</entry>
</map>
</property>
</bean>
The problem is in hibernate 5 I don't have EventListners and also I don't have IdTransferringMergeEventListener. Do I need this? How can I replace?

from api IdTransferringMergeEventListener
Extension of Hibernate's DefaultMergeEventListener, transferring the
ids of newly saved objects to the corresponding original objects (that
are part of the detached object graph passed into the merge method).
So if you don't use this in your project you can skip it. If you need it , you can just copy listener and register one. I think DefaultMergeEventListener has method onMerge(MergeEvent event, Map copiedAlready) that support old IdTransferringMergeEventListener
from IdTransferringMergeEventListener extends org.hibernate.event.def.DefaultMergeEventListener, which has been moved to org.hibernate.event.internal.DefaultMergeEventListener it should be ok.
We intentionally kept Spring's Hibernate 4 support rather minimal, in
order to stay close to the native Hibernate 4 ways of doing things. As
a consequence, we have no plans to reintroduce
IdTransferringMergeEventListener or any of our former LOB user types,
all of which were special-purpose classes to work around issues that
Hibernate should really solve itself - since they have nothing to do
with Spring and caused repeated maintenance headaches on Spring's
side.
You're free to create your own version based on Spring's old
IdTransferringMergeEventListener, of course. However, note that the
way that event listeners can be registered has changed in Hibernate 4:
This is not possible on a per-SessionFactory level anymore, hence
Spring cannot support in its LocalSessionFactoryBean either. Check the
corresponding Hibernate documentation and the corresponding reports on
the Hibernate JIRA for details.

Related

spring application takes too long to start

I have a java application in which I'm using Spring and Hibernate frameworks. On my production environment, it would take too long (upto an hour) to start the application properly, as in, within 10 minutes. I could see the login page but if I try to login, it would just keep processing. Only after an hour or so, I would be able to login.
After some research I found that by default hibernate.temp.use_jdbc_metadata_defaults is set to true, in which case it takes time, so I set it to false. Now my application is starting up quickly in my local system when I point it to production db to test. Even in test environment it performs as expected. But when I rolled it out to production, it worked fine initially but now it again is taking too long to start up.
Any idea how to approach it now?
EDITED: adding more details:
initial startup time is huge. once it is up then pages would load fine. we are using postgres db and have multiple schemas. Please suggest what other details are needed
Below is session factory onfiguration:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="mydb"/>
<property name="entityInterceptor" ref="nullToEmptyStringInterceptor" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.multiTenancy">SCHEMA</prop>
<prop key="hibernate.tenant_identifier_resolver">path_to.DataBaseResolver</prop>
<prop key="hibernate.multi_tenant_connection_provider">path_to.MultiTenantProvider</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>path_to_model_package</value>
</list>
</property>
</bean>
Below is entityManagerFactory configuration
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="mydb" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="jpaDialect" ref="jpaDialect" />
<property name="persistenceUnitName" value="myPersistenceUnit" />
<property name="packagesToScan" >
<list>
<value>path_to_model_package</value>
</list>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
<prop key="hibernate.jdbc.use_get_generated_keys" >true</prop>
</props>
</property>
</bean>
I don't think we can tell you what the problem is. It will be something to do what the applications is doing during startup, and we can only guess what that would be.
However ...
What you should do is to profile the application during startup, and use the profiling to identify where most of the time is being spent. Then look to see if you can work out what it its doing ... and optimize it.
It would also be work turning on GC logging to see if memory usage / garbage collection is part of the problem. Ditto for checking if database activity is a significant bottleneck.
Finally, an important step in finding the cause of this problem is likely to be understanding the internal architecture of the application. Especially if this is code that has been passed from developer to developer over a number of years.
As you did not posted full details of your problem, like hibernate, spring and other app configurations so suggesting you a solution is bit difficult. The following could be possibilities:
Somewhere there could be deadlock during application load time. For example, so batch job running in background before the container completely starts.
If your db schema is always checked to be updated after the container start and your db is having a large number of tables and columns with a lot of data inside then it would definitely take time before that application loading completes.
Check server configurations like if there is another instance of application running in parallel which is causing delay.

Spring app should start even though DB is down

I have a spring app which do minimal operations with DB.
And I have a requirment that my application should run under the absence of DB(or when db is down).Below is my datasource configuration.
<bean id="dt31DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" depends-on="systemPropertyInitializer"
p:driverClass="${dt31.driver_class}"
p:jdbcUrl="${dt31.url}"
p:user="${dt31.username}"
p:password="${dt31.password}"
p:idleConnectionTestPeriod="1000"
p:maxPoolSize="4"
p:minPoolSize="2"
p:maxIdleTime="2000"
p:unreturnedConnectionTimeout="600"
p:contextClassLoaderSource="library"
p:privilegeSpawnedThreads="true"
p:initialize=false
/>
<bean id="dt31SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dt31DataSource"/>
<property name="packagesToScan" value="com.t22.dt31"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
${dt31.dialect}
</prop>
<prop key="hibernate.show_sql">
false
</prop>
<prop key="hibernate.hbm2ddl.auto">
update
</prop>
</props>
</property>
</bean>
I found a page in google,saying to use "initialize: false" in spring data source configuration.But I am using "ComboPooledDataSource" datasource which does not have this property.Is there any other way to achieve this ?
The application service layer can operate with two DAO layers (file system and database), so when the DB is down you catch the connection acquire exception and switch to the file system instead.
Having two sources of truth is going to make it difficult to preserve consistency across two different data sources, especially if one resource is not available.
When both resources are available you can use XADisk and Bitronix for XADataSource and JTA transaction management.

Jersey Service Initialization with HIbernate default dataset

I have a stack that consists of Hibernate, Spring, and Jersey.
While a great deal of things are RESTFUL, not everything in our application is (and cannot be, for various reasons. I realize I break REST best practices in places.)
I need to do two things and cannot figure out how to make both happen.
in my application-context.xml I have the following
<!-- Configure the entity manager factory bean -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>
<property name="packagesToScan" value="com.mystuff.model"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.import_files">data.sql</prop>
</props>
</property>
This normally loads some hibernate data into the database for me.
However, I also need to initialize some in memory structures in the service.
The moment i try to have my service extend ServletContainer and override initiate despite a call to super.initiate()
or implement AbstractResourceModelListener and then provide onLoaded(AbstractResourceModelContext modelContext)
I am getting null pointers because my initial data provided by data.sql is not there.
How can I do this correctly so I both get my data.sql loaded and can execute a few statements when the service is loaded?
(If anyone is curious, yes the service is a #Singleton)
Any help appreciated.
So, it turns out the right answer here, is to use #PostConstruct despite the warnings eclipse may give you about restrictions and libraries. I'm not sure why that warning appears, or why it proceeds to work anyways, but #PostConstruct is the way to go to not trash other loading in Spring.
(That said, if you aren't pinned in, doing the initialization outside and injecting it is more RESTFUL and better and not needing #Singleton, but I assume in both the question and answer that it isn't an option for you for whatever reason.)

hibernate4.LocalSessionFactoryBean cannot be cast to org.hibernate.cfg.Configuration

It seems to be a common problem but I am not able to resolve it.
my Spring 3.1.1 configuration is
<bean id="sessionFactoryEditSolution" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="editSolutions-pool"/>
<property name="mappingResources">
<list>
<value>/editsolutions.hibernate.cfg.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop>
<prop key="net.sf.ehcache.configurationResourceName">/ehcache.xml</prop>
<prop key="hibernate.max_fetch_depth">6</prop>
<prop key="hibernate.default_schema">dbo</prop>
</props>
</property>
</bean>
And this how I am trying to get the configuration object
Configuration editSolutionsConfiguration = `(Configuration)AppContext.getBean("&sessionFactoryEditSolution");`
Initially I have Hibernate 3 for my application but to integrate it with Spring 3.1.1 I have upgraded it to Hibernate 4 .That's why I have to keep hibernate3.jar in my lib folder to support few hibernate 3 specific code lines.
A couple of notes:
you can't work with two versions of hibernate on the classpath. Your old code should be updated
&x returns the factory bean, it doesn't return the produced object. Even without the ampersand, this would return the SessionFactory, rather than Configuration.
with spring you don't need Configuration actually, it is handled behind the scene
we are working with hibernate 3 and spring 3.1. 3.1.1 might be different, but either keep the lower versions of both, or upgrade both (including code)

Java: DBunitils + Spring: Different Hibernate-Dialect

I currently use spring for depency injection. Hibernate uses a postgres dialect for the normal run, but I want to use HSQL for the DBUnitils Databank-Testing.
My Spring-Configuration contains this:
<!-- Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="use_outer_join">${hibernate.use_outer_join}</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.provider_class">${hibernate.cache.provider}</prop>
<prop key="hibernate.connection.pool_size">10</prop>
<prop key="hibernate.jdbc.batch_size">1000</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>de.dbruhn.relations.model.Relation</value>
<value>de.dbruhn.relations.model.RelationData</value>
<value>de.dbruhn.relations.model.RObject</value>
<value>de.dbruhn.relations.model.Type</value>
</list>
</property>
<property name="schemaUpdate" value="${hibernate.schemaUpdate}"/>
</bean>
The fields get replaced by maven resource-filtering.
The Spring-Configruation for DBUnitils contains this:
<bean id="dataSource" class="org.unitils.database.UnitilsDataSourceFactoryBean"/>
</beans>
and so overrides the dataSource from my run configuration with the UnitilsDataSource.
The Problem: I cant run the Tests using Postgres-Dialect against the HSQL-Test-Database because some commands dont work.
The only solution which came to my mind: Switching the resource-filter in maven, but I have to do this by hand (by provining a "-P TEST" on every maven call). So isn't there a possibilty to override the hibernate.dialect?
Thanks!
You normally don't need to specify the dialect at all, Hibernate will figure it out by looking at the underlying datasource. You only need to specify the dialect if you want to force Hibernate to use a specific one.
In your case, you should just be able to remove the dialect property completely, and it should work in postgres and hsql without config modification.
You should possibly look at using the PropertyPlaceHolderConfigurer in spring to change the config. That way you need only supply a different config file for the different environments, the spring xml stays the same.
And you can load the config file like this.

Categories