Shutdown Derby database using JPA not DriverManager - java

I have an RCP client application that uses embedded Derby in the same JVM for persistence. I access it via JPA using RESOURCE_LOCAL and Eclipse Link as a JPA provider. I leave starting the Derby instance to JPA and persistence.xml.
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME, props);
Persistence.xml
<properties>
<property name="eclipse.weaving" value="false" />
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="javax.persistence.jdbc.url" value="jdbc:derby:pathToDb" />
<property name="eclipselink.logging.level.sql" value="FINEST" />
<property name="eclipselink.logging.parameters" value="true" />
</properties>
At one point in the application, I need to stop the underlying Derby database. All of the examples show calling:
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
DriverManager.getConnection("jdbc:derby:pathToDb;shutdown=true");
This is problematic, especially in an RCP application with multiple class loaders (it uses OSGI under the covers). I have tried using
if (factory.isOpen())
factory.close();
but this does not shutdown the Derby instance, only the JPA connection to it.
Is there a way, using JPA, to shutdown the underlying Derby instance?
Update
I tried using the OSGI console to stop the persistence related bundles including javax.persistence, JPA and Derby. Stopping these did not release the file locks that Derby put on log files.
Update 2
Revised to clarify that the use is not in an OSGI server application.

The issue was not the classloader but an import issue.
An RCP application has a "target platform" that is dynamically searched by the framework for dependencies. This does not happen when calling Class.forName(). Once I explicitly added the Derby jar to my bundle's dependencies, the class was found and the database is shutting down properly.
Lesson learned: check the simple stuff before assuming it is hard!

Related

Hibernate creating Schemas on each application run?

I have built a web application using MVC pattern and Hibernate. I am trying to configure my hibernate to create schemas for my classes by using following property
<property name="hibernate.hbm2ddl.auto">create</property>
But, I found out that this drops the previous existing schema and re-creates schema on each application run. Is there anyway I configure my hibernate to create schemas only on my first application run and for any future application run just update the rows in existing database?
As YomanTaMero mentioned instead of :
<property name="hibernate.hbm2ddl.auto">create</property>
try this:
<property name="hibernate.hbm2ddl.auto">update</property>
Noticed "update" above?

Liquibase + JPA: Run order

I have a Java Project in which I use JPA for persistence.
Now I want to integrate LiquiBase in my project, but I don't know how to change the order JPA/Liquibase are executed.
For clarity:
Until now my persistence.xml looks like this:
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value=.../>
<property name="javax.persistence.jdbc.user" value=.../>
<property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
I now tried to set:
<property name="eclipselink.ddl-generation" value="none"/>
so that liquibase handles all the database-stuff.
But now when I run my Code, JPA throws an Error because some tables are missing, although these tables should be created by liquibase, which leads me to believe that JPA is running before liquibase.
How do I change that order?
Until now, Liquibase is executed in code via this lines:
java.sql.Connection connection = openConnection(); //your openConnection logic here
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
Liquibase liquibase = new liquibase.Liquibase("path/to/changelog.xml", new ClassLoaderResourceAccessor(), database);
liquibase.update(new Contexts(), new LabelExpression());
I read somewhere that this could be achieved via Liquibase Servlet listener, but that requires the database data-source, and I dont know how to get that.
Liquibase itself works fine.
If you want to run Liquibase as part of your application I recommend to use one of the options documented in the "Automated" section:
http://www.liquibase.org/documentation/running.html
Servlet Listener
Spring Listener
JEE CDI Listener
If you're developing a Java EE application, first create a data source:
https://docs.oracle.com/javaee/7/tutorial/resource-creation002.htm
Note that this is application server specific.
Since Java EE 6 there is now also an application server independent annotation which can be used: http://docs.oracle.com/javaee/7/api/javax/annotation/sql/DataSourceDefinition.html
In your persistence.xml I suggest to use transaction-type="JTA" and reference the data source using:
<jta-data-source>jdbc/someDB</jta-data-source>
Omit the part:
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value=.../>
<property name="javax.persistence.jdbc.user" value=.../>

Can't achieve working with p6Spy

I've tried two methods for adding p6Spy feature to my spring used project.
Route I,
http://templth.blogspot.com.tr/2004/11/integrate-p6spy-with-spring.html
I changed my driver with com.p6spy.engine.spy.P6SpyDriver and added realdriver realdriver=com.ibm.db2.jcc.DB2Driver into spy.properties file.
But somehow my realdriver is being registered before p6spy driver com.ibm.db2.jcc.DB2Driver is a real driver in spy.properties, but it has been loaded before p6spy. p6spy will not wrap these connections.Either prevent the driver from loading, or try setting 'deregisterdrivers' to true in spy.properties
Using :p6spy: prefix doesn't work for me. It says can't establish connection with that url.
So,I chose setting this deregisterdrivers=true in property file.
This time I get sql in log file but can't execute sqls. I'm able to execute sql in another sql editor. It seemed real connection went and a dummy one came.
Route II,
We use spring. So I've tried this method. Giving datasource explicitly to p6Spy. But this time spring complained of multiple java.sql.DataSource instance. Both com.firm.BasicDataFill and com.p6spy.engine.spy.P6DataSource implements DataSource. Spring can't obtain a singleton.
http://templth.blogspot.com.tr/2004/11/integrate-p6spy-with-spring.html
<bean id="dataSource" lazy-init="true"
class="com.firm.BasicDataFill">
<property name="driverClassName" value="${database.connection.driver_class}" />
<property name="username" value="${database.connection.username}" />
<property name="password" value="${database.connection.password}" />
<property name="url" value="${database.connection.url}" />
...
<property name="accessToUnderlyingConnectionAllowed" value="true" />
</bean>
<!-- bean id="myDataSource" class="com.p6spy.engine.spy.P6DataSource">
<constructor-arg>
<ref local="dataSource"/>
</constructor-arg>
</bean-->
Finally, I discovered p6spy v1.3 and 2.4.1 settings vary. Do you have any suggestion for a spring based application.
I would recommend starting with the latest version of P6Spy 2.x. You should also REPLACE your spy.properties file with the default version for 2.X which is documented here. Depending on your application server, you might need to set the 'realdriver' setting in spy.properties to include 'com.ibm.db2.jcc.DB2Driver'. However, this is only needed when you are using an application server that prevents the automatic registration of JDBC Drivers.
To use P6Spy with Spring, the easiest method is to wrap your current data source bean with P6SpyDataSource as discussed here. The example in that answer shows a JNDI data source being wrapped but it can be used to wrap any data source. Note: If you are wrapping the data source is P6SpyDataSource, you do NOT need to modify the JDBC URL.
If you continue to have problems, please add a bit more information to your question. The following information would be helpful in troubleshooting:
The version of P6Spy being used
The contents of spy.properties
The definition of your datasource (including app server config if
using JNDI)
The type of app server and version being used
Stacktrace containing whatever error you might have received.
Have a look at Log4jdbc it'll do the job https://code.google.com/p/log4jdbc/

Configuring Infinispan as remote second level cache for Hibernate

As per Infinispan documentation the following settings make up setting infinispan as a L2 Cache provider for Entities
<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.use_query_cache" value="true" />
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.infinispan.InfinispanRegionFactory"/>
Then further one can annotate Entities with #javax.persistence.Cacheable to make them candidate for L2 cache.
My question is how to make this a remote cache ?
Infinispan 2LC implementation for remote cache does not exist. You could maybe configure the embedded caches used for Infinispan 2LC with a remote cache store which talks to one or multiple Infinispan Servers. Please note that this has not been tested and there's no guarantees that it'll work as expected due to the peculiarities and the optimizations done by the embedded Infinispan 2LC implementation.

Spring’s embedded H2 datasource and DB_CLOSE_ON_EXIT

For unit tests (call them integration tests if you want) I have configured an embedded database in my Spring config like so:
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:schema_h2.sql" />
</jdbc:embedded-database>
Now, when running the tests from the command line, they work fine, but I get some errors at the end (harmless, but irritating):
WARN 2013-03-25 12:20:22,656 [Thread-9] o.s.j.d.e.H2EmbeddedDatabaseConfigurer 'Could not shutdown embedded database'
org.h2.jdbc.JdbcSQLException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-170]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:329) ~[h2-1.3.170.jar:1.3.170]
...
at org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactoryBean.destroy(EmbeddedDatabaseFactoryBean.java:65) [spring-jdbc-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:238) [spring-beans-3.2.1.RELEASE.jar:3.2.1.RELEASE]
Now the tip contained in the exception is fine in general, but how do I add this attribute to the embedded datasource? Do I have to expand it, configure it by hand so to speak, to add such ‘advanced’ features?
Specify parameter in JDBC url jdbc:h2:~/test;DB_CLOSE_ON_EXIT=FALSE
Also for in-memory test database I suggest you to add DB_CLOSE_DELAY=-1, like this:
jdbc:h2:mem:alm;MODE=Oracle;DB_CLOSE_DELAY=-1
To add JDBC connection url to embedded-dababase change it to:
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:mem:test;MODE=Oracle;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
<jdbc:script location="classpath:schema_h2.sql" />
</jdbc:initialize-database>
I had the same issue as Michael Piefel's one and tried to implement the solution that Michail Nikolaev explained.
but it did not work, somehow spring-batch, then, where are the metadata JOB_* tables are.
So, as the version of spring-jdbc used by my application is 3.0.5 and increasing the spring-framework one enters in conflict with dwr (i use it in my app) it's a geo localization based on spring, dwr and gmaps api.
I downloaded the spring-jdbc 4.0.3 release and get from it the H2EmbeddedDatabaseConfigurer.class who has DB_CLOSE_ON_EXIT=FALSE by default and replace with it the one on the spring-jdbc 3.0.5 Release and deploy-it in the war file and it works, the shutdown of the VM didn't provoke the closing of the in-memory database.
Hope this unusual solution helps if other people like me wouldn't be able to implement the other solution.
I had the same problem, but it was because I forgot to add the annotation #Entity on one of my entities. I add it and it work now !
I hope this helps someone.

Categories