Class autodetection in persistence.xml from src/test - java

I have a persistence.xml at src/main/resources/META-INF/ and another at src/test/... which differ only in the value of the database:
<properties>
<property name="hibernate.archive.autodetection" value="class, hbm"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/lanchecker-prod" />
and:
<properties>
<property name="hibernate.archive.autodetection" value="class, hbm"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/lanchecker-test" />
However I'm also using class autodetection which works fine for the main resource but fails when I use the test resource.
Is there any way to get this to work or am I obliged to use explicit class naming?
EDIT:
The linked suggestion doesn't actually work it it requires the project is built and tested as a .jar. In my case I'm attempting to do the testing under Eclipse, which can resolve the src/test/resources/META-INF/ location.
I tried adding:
<jar-file>${PROJECT_LOC}/src/main/java/biz/ianw/lanchecker/</jar-file>
but that resulted in:
Exception in thread "main" java.lang.ExceptionInInitializerError
...
Caused by: javax.persistence.PersistenceException: Unable to build entity manager factory
...
Caused by: java.lang.IllegalArgumentException: Unable to visit JAR file:${PROJECT_LOC}/src/main/java/biz/ianw/lanchecker/. Cause: Illegal character in opaque part at index 6: file:${PROJECT_LOC}/src/main/java/biz/ianw/lanchecker/
And then:
<jar-file>C:\Users\Ian\git\LANchecker\src\main\java\biz\ianw\lanchecker\</jar-file>
which passed entity manager factory startup, but still failed later with:
Exception in thread "main" java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: RouteCabinFares is not mapped [select rcf from RouteCabinFares rcf]
(RouteCabinFares is one of the classes I'm attempting to autolocate).
Maybe this technique can only be used to autolocate in jar files?

As far as I can tell what I'm trying to do here is not possible.
The best work around I've come up with is to remove the properties you wish to vary from the persistence.xml, in this case:
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/lanchecker-test" />
and specify them at runtime using code similar to:
Properties properties = new Properties();
properties.setProperty("hibernate.connection.url", "jdbc:mysql://localhost/lanchecker-test");
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("lanchecker", properties);
The actual property values can then be injected at runtime via Spring. This involves separating standard properties into persistence.xml and varying properties into spring.xml and is, to my mind, extremely hokey.
I get the impression that Spring Boot might offer a simpler solution but at the expense at another framework so, for the moment, the above is what I'm going for.

Related

java.lang.ClassNotFoundException When Filepath is Correct

I'm working with Spring right now and have been trying to resolve a number of Failed to load ApplicationContext errors. This latest one is because it can't find a specific class when creating a bean structured like the following:
<bean id="problematicBean"
class="com.domain.application.search.problematicBean">
<property name="missingClass">
<bean class="com.domain.application.search.MissingClass">
</bean>
</property>
</bean>
I've triple checked and the filepath used in the bean class is correct. Other beans with identical paths (at least to the point of applicaiton) work perfectly. The file exists exactly where it should be for this classpath to work. The only difference is that this is a groovy file. Does anyone know why my application can't find the class?

GWT + IntelliJ Idea - adding a server side library

I am trying to implement a GWT project in IntelliJ Idea 15. I have no problems (at least obvious) with GWT and its superdev mode - I can run an application and play with it. I can do RPC calls.
However, now I am trying to add JPA/Hibernate support to use a database. And here I have troubles. In the project I have a GWT facet (2.6.1), a JPA facet (with hibernate implementation), and a web facet (for web dd). Using Open Module Settings -> Libraries -> New Project Library I have added gwt-servlet.jar, and using maven (its not a maven project, just using the feature of Idea) libraries: c3p0:c3p0:0.9.1.2, org.hibernate:hibernate-entitymanager:5.0.3.Final, org.postgresql:postgresql:9.3-1101-jdbc41 ; that is the configuration.
Using this persistence unit properties (excerpt):
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
<property name="hibernate.c3p0.min_size" value="5" />
<property name="hibernate.c3p0.max_size" value="20" />
<property name="hibernate.c3p0.timeout" value="300" />
<property name="hibernate.c3p0.max_statements" value="50" />
<property name="hibernate.c3p0.idle_test_period" value="3000" />
In GWT RPC servlet I try to create EntityManager instance:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("ThreatPersistenceUnit");
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("SELECT a FROM Asset a");
...
But when I try to run it in the IDEA using default GWT run configuration (Jetty), I get following exception:
javax.persistence.PersistenceException: Unable to build entity manager factory
caused by
Caused by: java.lang.ClassNotFoundException: Could not load requested class : org.postgresql.Driver
Also, before the exception I get following warning:
WARN: HHH000022: c3p0 properties were encountered, but the c3p0 provider class was not found on the classpath; these properties are going to be ignored.
So it seems the server cannot see both c3p0 and postgre jdbc driver.
I tried to google, the closest problem/solution I found is this SO answer. I have put the libraries both to the project and to the artifact. However, I am not sure what the replier meant by the Jetty lib. Where would I find Jetty installation, if I am using just the GWT's default server?
Plus, what seems quite weird to me is that before I had a similar problem (I dont remember if it was exactly the ClassNotFoundException) with GWT RPC that I was able to resolve by adding a gwt-servlet.jar to the libraries - why then adding these other libraries does not help? At least it seems that it does not have any problems with hibernate, since it provides the warnings and so on.
OK, even though it is a stupid mistake, maybe someday in the future someone else will make it, so for future reference this was the issue:
I had set the SDK and sources version of the project as 1.6; the hibernate and other libraries seem to been compiled in the same or lower version. However, the postgre driver was compiled using a newer version - when I have set the source version to 1.7 and set as an SDK the Java 8 SDK, the program crashed at some different exception (but that was due to my programming error - unrelated). I found this out only after I tried (in total desperation) to create a new object of the driver manually in the code (not to delegate the creation to persistence provider) - then I got the major minor version exception and I knew what is the problem.

JPA/Hibernate finds no mapped classes after deployment

Short Version
I've got a Java-project which uses JPA 2.0 with Hibernate 4.3.4. All is fine when I run it inside Eclipse. But when I let Eclipse export a runnable JAR, the trouble begins and the program crashes due to a seemingly missing persistence unit...
javax.persistence.PersistenceException: No Persistence provider for EntityManager named MyDBManager
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:61)
... or seemingly unmapped classes...
3024 Thread-4| FATAL DbManager : DBManager could not load countries from database.
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Country is not mapped [SELECT x FROM Country x]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1750)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:331)
Background
Depending on the kind of export (extracting vs. packaging vs. copying libraries), I run into different errors which resist solving. The furthest I get is with the last approach, which is also the one I have to choose for license reasons, so let's focus on that one.
In this case the exported JAR fails to look into its persistence.xml. I will specify that later but first some background information...
Folder Structure
some_folder
myproject_lib
myproject.jar
root of my project's package structure
meta-inf
persistence.xml
File persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="MyDBManager" transaction-type="RESOURCE_LOCAL">
<!-- <exclude-unlisted-classes>false</exclude-unlisted-classes> -->
<!-- <class>isi.eload.core.Country</class> -->
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<!-- Do not define a connection here - this is done by the DbManager according to the command line arguments -->
<property name="hibernate.id.new_generator_mappings" value="true" />
<!-- <property name="hibernate.archive.autodetection" value="class, hbm" /> -->
</properties>
</persistence-unit>
</persistence>
I played around with the commented lines, once I felt that the xml is actually processed (see below) but that didn't help.
JPA/Hibernate JARs
Essentially the ones from the 4.3.4 Final Release:
antlr-2.7.7
dom4j-1.6.1
hibernate-commons-annotations-4.0.4.Final
hibernate-core-4.3.4.Final
hibernate-entitymanager-4.3.4.Final
hibernate-jpa-2.1-api-1.0.0.Final
jandex-1.1.0.Final
javassist-3.18.1-GA
jboss-logging-3.1.3.GA
jboss-logging-annotations-1.2.0.Beta1
jboss-transaction-api_1.2_spec-1.0.0.Final
.
Failing with persistence.xml
Packaged meta-inf
As I hinted at before, the exported JAR fails to properly process the persistence.xml. When I execute it in the above folder structure, the following exception is thrown:
javax.persistence.PersistenceException: No Persistence provider for EntityManager named MyDBManager
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:61)
This exception is usually thrown when the file was found but the persistence unit name given to Persistence.createEntityManagerFactory does not match any persistence unit declared in the files. But this is definitely not the case here!
I have no good idea, why this exception is thrown.
When I edit the JAR file (though I'm not sure that such tampering is not causing problems on its own) and empty or remove the persistence.xml, the error stays the same.
Another meta-inf
My first response was to copy a meta-inf folder next to the JAR:
myproject_lib
myproject.jar
... unchanged ...
meta-inf
persistence.xml
This seems to work, as an entity manager factory can now be created. But then no Entities are found and I think this is related to the fact that the persistence.xml, which is actually used, is not "on the same class path" as the JAR file.
Is there a link or an idea for how I can fix this? Preferably by forcing the JAR file to use the meta-inf folder which it contains itself.
META-INF needs to be in upper case. If Java is attempting to access the filesystem on Windows (or OS X in that regard) META-INF/persistence.xml will be automatically translated to meta-inf/persistence.xml by the operating system. Once you package it up to a JAR it becomes case sensitive and stops working.

Why can I run JUnit tests for my Spring project, but not a main method?

I am using JDBC to connect to MySQL for a small application. In order to test without altering the real database, I'm using HSQL in memory for JUnit tests.
I'm using Spring for DI and DAOs. Here is how I'm configuring my HSQL DataSource
<bean id="mockDataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:mem:mockSeo"/>
<property name="username" value="sa"/>
</bean>
This works fine for my JUnit tests which use the mock DB. But when I try to run a main method, I find the following error:
Error creating bean with name 'mockDataSource' defined in class path resource [beans.xml]:
Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'driverClassName' threw exception; nested exception is java.lang.IllegalStateException:
Could not load JDBC driver class [org.hsqldb.jdbcDriver]
I'm running from Eclipse, and I'm using the Maven plugin. Is there a reason why this would work as a Test, but not as a main()? I know that the main method itself is not the problem, because it works if I remove all references to the HSQL DataSource from my Spring Configuration file.
m2eclipse won't add your test-scoped dependencies to the classpath when you run the application as 'Java Application'. You will need to change the scope of the hsql dependency to 'compile' (the default) for that to happen.

Hibernate is not able to load a JAR file if my directory name contains space!

I have an application that is based on Swing, Spring 2.5.2, Hibernate 3.3.1.
If my application is run from a directory that contains a space character, for example D:\hudson\jobs\FooBar - Fast Build, then I get this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [spring-persistence.xml]: Invocation of init method failed; nested exception is java.lang.RuntimeException: error trying to scan <jar-file>: file:/D:/hudson/jobs/FooBar%20-%20Fast%20Build/workspace/commons/target/classes/
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1302)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:463)
...
Caused by: java.lang.RuntimeException: error trying to scan <jar-file>: file:/D:/hudson/jobs/FooBar%20-%20Fast%20Build/workspace/commons/target/classes/
at org.hibernate.ejb.Ejb3Configuration.scanForClasses(Ejb3Configuration.java:635)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:350)
...
Caused by: java.lang.RuntimeException: java.io.FileNotFoundException: D:\hudson\jobs\FooBar%20-%20Fast%20Build\workspace\commons\target\classes (The system cannot find the path specified)
at org.jboss.util.file.JarArchiveBrowser.<init>(JarArchiveBrowser.java:74)
at org.jboss.util.file.FileProtocolArchiveBrowserFactory.create(FileProtocolArchiveBrowserFactory.java:48)
...
Caused by: java.io.FileNotFoundException: D:\hudson\jobs\FooBar%20-%20Fast%20Build\workspace\commons\target\classes (The system cannot find the path specified)
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(ZipFile.java:114)
at java.util.jar.JarFile.<init>(JarFile.java:133)
at java.util.jar.JarFile.<init>(JarFile.java:97)
at org.jboss.util.file.JarArchiveBrowser.<init>(JarArchiveBrowser.java:69)
... 49 more
(note that in this case, the error occurs during a unit test launched by a Hudson job)
As you can see, each space character is replaced by a %20 in the URL, which may be the source of the problem...
Do you have any idea why this happens, and how to solve it (of course, renamming the whole path of my application will solve the problem, but it is not the kind of answer that I am looking for ;) ) ?
ps: I don't know if it can help you, but the bean entityManagerFactory is created in the spring-persistence.xml file with the following definition:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="oraclePersistenceUnit"/>
<property name="dataSource" ref="dataSource"/>
</bean>
(the properties are defined in another place of the spring definition, or in a persistence.xml file)
The error is thrown when I run the following code in my application:
applicationContext = new ClassPathXmlApplicationContext("/my-spring-config.xml");
my-spring-config is located in the src/main/resources directory of my application.
I've also tested with a FileSystemXmlApplicationContext instead, but the problem still occurs.
The %20 is the normal way to URL-encode spaces.
Sounds like you are treating an URL like a plain filename, which is incorrect. How is this information passed down to Ejb3Configuration?
In fact, this is due to a bug in the version of hibernate-entitymanager I was using (3.3.1.ga).
By replacing this version with the latest one (3.4.0.GA), the problem does not occur anymore.

Categories

Resources