default for persistence.xml variable set by environment variable - java

tl;dr: I want to fill a variable in the persistence.xml with an environment variable, or have it be a previously defined default if no such environment variable exists.
I want to set the default scheme of Hibernate in my persistence.xml dynamically on start-up in Docker.
Therefore i added a variable into the following property, which can be set by using an environment variable:
<property name="hibernate.default_schema" value="${env.DB_SCHEME}"/>
This works perfectly fine for the docker environment, but for the non-docker environment i need some kind of default value that gets injected.
Sadly i cant use something like this, because it is not supported:
<property name="hibernate.default_schema" value="${env.DB_SCHEMA:my_default_scheme}"/>
I also tried adding a property env.DB_SCHEME to the Maven properties of the project,
but that way it always uses the value from Maven and i can't override it with environment variables anymore.
Another thing i read about was to use the filtering option from the resource plugin in Maven. That way i could replace the variable with a pre-defined value.
But that way i have to select a profile while building and it's not possible to change at runtime.
Further i tried doing it programatically. Therefore i took the entityManager of my persistence-unit and checked, whether the environment-variable was set or not.
If it was set (only while using the docker environment) it should have placed the ${env.DB_SCHEME} in the value of the property.
Otherwise it could have placed ${DB_SCHEME} in it, so that the property from Maven could later overwrite it.
But somehow, the properties aren't set. Maybe the code is executed too late, because the property hibernate.hbm2ddl.auto" is set to validate.

In case you are using Payara application container (version >= 4.1.2.172), you can user a syntax like this:
${ENV=PG_DATASOURCE_NAME}
My persistence.xml file for example:
<?xml version="1.0" encoding="UTF-8"?>
<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://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="${ENV=PG_DATASOURCE_NAME}" transaction-type="JTA">
<jta-data-source>${ENV=PG_DATASOURCE_NAME}</jta-data-source>
<properties>
<property name="hibernate.show_sql" value="true"/>
<property name="javax.persistence.sharedCache.mode" value="NONE" />
</properties>
</persistence-unit>
</persistence>
More on this topic at the docs.

Related

How do I make JNDI names compatible with both GlassFish and WildFly

I am developing a Java EE 7 application and have a requirement for the application to be deployed onto application servers running either GlassFish 4.0 or WildFly 8.1.0. The issue I've got is GlassFish and WildFly use slightly different formats for JNDI names but I can't see how to make my application compatible with both.
In GlassFish my persistence.xml file references the data source jdbc/myDataSouce, but in WildFly the data source needs to be java:/jdbc/myDataSource.
The same is also true for classes that are annotated with #Resource. In GlassFish the annotation for a class using JavaMail would be #Resource(name = "mail/myMailSession"), but to deploy onto WildFly this would need to be #Resource(name = "java:mail/myMailSession").
I know that I could unpack the EAR and JAR files to manually edit files such as persistence.xml but I can't do that for classes that have been annotated with #Resource.
Is there a way I can allow my complied application to be deployed onto GlassFish and WildFly without maintaining two different versions of the code? I'm assuming the answer probably lies with application specific deployment descriptors but I can't find any examples that cover these two scenarios.
Can anyone point me in the right direction please?
You can modify the Wildfly JNDi names and strip the undesired prefixes from the respective JNDI names to find the least common denominator in both app servers. The following works for me with Glassfish and JBoss AS 7.1. Since I expect Wildfly to be backwards-compatible to JBoss in this regard, I guess it'll work for Wildfly as well.
Persistence
Inject as:
#PersistenceContext(unitName="TestPU")
private EntityManager entityManager;
or via ejb-jar.xml:
<persistence-context-ref>
<persistence-context-ref-name>entityManager</persistence-context-ref-name>
<persistence-unit-name>TestPU</persistence-unit-name>
<injection-target> ... </injection-target>
</persistence-context-ref>
The corresponding persistence.xml:
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/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">
<persistence-unit name="TestPU" transaction-type="JTA">
<jta-data-source>datasources/TestDS</jta-data-source>
<class>org.jeeventstore.persistence.jpa.EventStoreEntry</class>
<properties>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.connection.charSet" value="UTF-8"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
</properties>
</persistence-unit>
</persistence>
(note the simple jta-data-source JNDI name)
Here's a glassfish-resources.xml file used to specify a Derby database on deployment, a similar setup can be used for MySQL or Postgres.
<resources>
<jdbc-resource pool-name="ArquillianEmbeddedDerbyPool"
jndi-name="datasources/TestDS"/>
<jdbc-connection-pool name="ArquillianEmbeddedDerbyPool"
res-type="javax.sql.DataSource"
datasource-classname="org.apache.derby.jdbc.EmbeddedDataSource"
is-isolation-level-guaranteed="false">
<property name="databaseName" value="target/databases/derby"/>
<property name="createDatabase" value="create"/>
</jdbc-connection-pool>
</resources>
And the settings from the JBoss standalone.xml:
<datasource jta="true" jndi-name="java:/datasources/TestDS" pool-name="TestDS" enabled="true" use-ccm="false">
<connection-url>jdbc:postgresql://localhost/test_db</connection-url>
...
</datasource>
Resources
I have not injected a JavaMail component on Glassfish, but similar to the datasoruce settings, it might be worth a try to strip the "java:" part from the #Resource annotation as well.
#Resource(name = "mail/myMailSession")
and then configure Wildfly such that that the mail resource is available at the "java:mail/myMailSession" JNDI location.
Injection via ejb-jar.xml
Another option is to manually inject the fields via a ejb-jar.xml file, and then use a build tool such as maven to copy either of ejb-jar-glassfish.xml or ejb-jar-wildfly.xml to the desired ejb-jar.xml at assembly time.
In one of our projects we use a mixed approach to avoid the burden with the xml configuration: We configure a small number of "provider" beans via ejb-jar.xml to inject, e.g., the persistence context into a PersistenceContextProvider, and then use CDI to inject the PersistenceContextProvider into the EJBs via #EJB, which are found without further configuration since they reside in the same EAR.
I haven't hit the mail-dilemma just yet. But I've ran into the same problem your having when it comes to data source definition and my solution has been to not setup the data sources using the server's console, but make them deployable together with your archive using the #DataSourceDefinition annotation. Turns out WildFly won't complain about java:app/blabla.. if the data source is setup during deployment!
Here is a real world example for you that works on both GlassFish and WildFly:
https://github.com/martinanderssondotcom/java-ee-concepts/../ArquillianDS.java
Note that the data source JNDI name declared is:
java:app/env/ArquillianDS
And here is the related persistence.xml file (don't mind the name of the file in this repository, the repository represents a test project that build archives during runtime and the app will change the name of the file in the archive to persistence.xml):
https://github.com/MartinanderssonDotcom/java-ee-concepts/../persistence-update.xml
Also note that the persistence unit need a data source located using this JNDI name:
java:app/env/ArquillianDS
This deployment works perfectly fine with both GlassFish and WildFly. I've noted that if we declare the data source during deployment, then we pay the price of not seeing the data source listed anywhere in the admin gui/console. For me, that is a small price to pay in order to have a truly portable application. As an added bonus, I don't have to write lengthy installation/setup instructions. For all my projects, the data source is an intrinsic part of the application and I don't mind having a class file in the archive that represents the data source.
The above data source is using a Java DB (or "Apache Derby" for old school people). As some comments in the ArquillianDS.java file describe: GlassFish has problems using a simple URL connection string combined with Java DB. Hence I resorted to specifying all attributes of the #DataSourceDefinition explicitly. Recently in another project of mine (alas not a public one), I used the same construct of deployment time data source definition but targeting MySQL. Here's that data source definition and it works on both servers:
#DataSourceDefinition(
name = "java:app/env/maLivechatDS",
url = "jdbc:mysql://localhost:3306/malivechat_db?createDatabaseIfNotExist=true&user=root&password",
className = "com.mysql.jdbc.jdbc2.optional.MysqlDataSource"
)
#ManagedBean
public class MySQLDataSource { }
Note that the driver is MysqlDataSource and not MysqlXADataSource. One point in my application uses a rather complex transaction scheme and GlassFish ran into problems if I used the XA-driver. However, the non-XA driver used by my application still work properly with JTA transactions so for me, it was just a cheap trick to get the boat floating. You should probably use the XA-driver.
For JNDI Portability with portable DataSourceDefinition annotation, I test it On payara-5.192, wildfly-17.0.1, tomee-8-M3 and openLiberty-19.0.0.7
#DataSourceDefinition(
name = "java:app/env/jdbc/mysql_app_name",
className = "com.mysql.cj.jdbc.MysqlConnectionPoolDataSource",
url = "jdbc:mysql://localhost:3306/db_name?characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&user=root&password=password",
minPoolSize = 1,
properties = {"characterEncoding=utf-8","zeroDateTimeBehavior=CONVERT_TO_NULL"})
I used it with MySQL connector 8.
refer to reference. for wildfly I created a startup bean class for configuration and set the annotation in the startup class.
for openLiberty add in server.xml
<application id="app_name" contextRoot="/app_name" name="app_name" location="../app_name.war" type="war">
<classloader commonLibraryRef="mysql"/>
</application>
<library id="mysql">
<file name="/path_to/mysql-connector-java-8.0.17.jar"/>
</library>
and put the war file in
usr/servers/defaultServer
folder

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.

How to externalize properties from JPAs persistence.xml?

I would like to put some of the hibernate configuration in a property file to make it editable without build and deploy.
I tried to solve my problem by following the instructions from Create JPA EntityManager without persistence.xml configuration file
app.properties:
hibernate.show_sql=true
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.hbm2ddl.auto=validate
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.default_schema=myschema
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- Persistence deployment descriptor for dev profile -->
<persistence xmlns="http://java.sun.com/xml/ns/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_1_0.xsd"
version="1.0">
<persistence-unit name="pu">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/appDatasource</jta-data-source>
<properties>
<property name="jboss.entity.manager.factory.jndi.name" value="java:/appEntityManagerFactory"/>
</properties>
</persistence-unit>
</persistence>
In the initialization code the application executes the following sequence, (which finds the properties),
Properties props = new Properties();
InputStream is = ClassLoader.getSystemResourceAsStream( "app.properties" );
props.load( is );
Persistence.createEntityManagerFactory( "pu", props );
but fails with the error message:
INFO [SessionFactoryImpl] building session factory
INFO [SessionFactoryObjectFactory] Not binding factory to JNDI, no JNDI name configured
ERROR [STDERR] javax.persistence.PersistenceException: [PersistenceUnit: pu] Unable to build EntityManagerFactory
Does anyone have an idea what could be wrong with my configuration?
Versions: JBoss 4.3
Seam: 2.1.2
EDIT:
JBoss JNDI enlists "pu" as persistence unit:
persistence.units:ear=app.ear,jar=app.jar,unitName=pu (class: org.hibernate.impl.SessionFactoryImpl)
As an alternative to your current approach and since you're using Hibernate, you could use Hibernate to configure JPA by declaring a hibernate.cfg.xml file using the hibernate.ejb.cfgfile property, like this:
<persistence>
<persistence-unit name="manager1" transaction-type="JTA">
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
<property name="hibernate.ejb.cfgfile" value="/hibernate.cfg.xml"/>
</properties>
</persistence-unit>
</persistence>
My understanding is that the hibernate.cfg.xml is just supposed to be on the classpath (so it could be outside the packaged archive).
References
Hibernate Entity Manager Reference Guide
Table 2.1. Hibernate Entity Manager specific properties
Just found a an alleged way for EclipseLink users. There is "eclipselink.persistencexml" which has a default value of
public static final String ECLIPSELINK_PERSISTENCE_XML_DEFAULT = "META-INF/persistence.xml";
but it can't be overridden although the docs say it can be...
/**
* The <code>"eclipselink.persistencexml"</code> property specifies the full
* resource name to look for the persistence XML files in. If not specified
* the default value defined by {#link #ECLIPSELINK_PERSISTENCE_XML_DEFAULT}
* will be used.
* <p>
* IMPORTANT: For now this property is used for the canonical model
* generator but it can later be used as a system property for customizing
* weaving and application bootstrap usage.
* <p>
* This property is only used by EclipseLink when it is locating the
* configuration file. When used within an EJB/Spring container in container
* managed mode the locating and reading of this file is done by the
* container and will not use this configuration.
*/
I used this mechanism, seems to work for most of the properties, had issues with non-jta-data-source.
http://www.eclipse.org/eclipselink/api/2.4/index.html?org/eclipse/persistence/config/PersistenceUnitProperties.html
If you are using Spring to manage and inject entity manager, then it is possible to implement org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor and pass on external properties. I could successfully externalize all properties from persistence.xml using this.

Decouple a JPA entities jar from persistence.xml in SE environment

Is there a way to reuse a jar with JPA annotated entities in more than one SE applications (as a dependency)? <jar-file> in persistence.xml is not supported in SE environments so is there another way?
Officially (per specification), you have to specify all classes using the class element. Quoting the chapter 6.2.1.6 mapping-file, jar-file, class, exclude-unlisted-classes of the JSR-220:
A list of named managed persistence classes may also be specified instead of, or in addition to, the JAR files and mapping files. Any mapping metadata annotations found on these classes will be processed, or they will be mapped using the mapping annotation defaults. The class element is used to list a managed persistence class. A list of all named managed persistence classes must be specified in Java SE environments to insure portability. Portable Java SE applications should not rely on the other mechanisms described here to specify the managed persistence classes of a persistence unit. Persistence providers may also require that the set of entity classes and classes that are to be managed must be fully enumerated in each of the persistence.xml files in Java SE environments.
Now, if you don't mind being not portable, Hibernate supports using the jar-file element in Java SE (in this case an absolute url is needed, not handy). Hibernate actually also supports auto-detection even in JSE. Much better:
<persistence xmlns="http://java.sun.com/xml/ns/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_1_0.xsd"
version="1.0">
<persistence-unit name="foo">
<!-- This is required to be spec compliant, Hibernate however supports auto-detection even in JSE. -->
<class>foo.Bar<class>
<properties>
<!-- Scan for annotated classes and Hibernate mapping XML files -->
<property name="hibernate.archive.autodetection" value="class, hbm"/>
...
</properties>
</persistence-unit>
</persistence>
As far as I know, there is no way to get the class scanning for annotations to work in that configuration. You can however explicitly point your persistence.xml file at each entity class.
<persistence xmlns="http://java.sun.com/xml/ns/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_1_0.xsd"
version="1.0">
<persistence-unit name="punit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/myDS</jta-data-source>
<!-- Must be explicit as classes are in separate jar -->
<class>com.foo.Bar</class>
<class>com.foo.Baz</class>
<properties/>
</persistence-unit>
</persistence>
From my experience - It now works.
We are using:
Hibernate3.jar 3.6.0.Final
hibernate-jpa-2.0-api-1.0.0.Final.jar
The < jar-file >file:...< /jar-file > knows how to look for relative paths - and it works both for jar files or directories.
I'm using this ability twice:
with a Jar holding my entities - which is used in several apps. each app has it's own persistence.xml - mainly to provide different ehcache settings.
With Junits when I want all my tests, in all other dependent projects to have a single persistence.xml file that will point to all the entities in the entities project. Then we keep the persistence.xml in the entities project under test/resources/META-INF pointing to the Bin directory of that project:
< jar-file >file:../entities/bin< /jar-file >
This was a problem I ran into. Slightly more preverse as I need to run several jar standalone as well as part of a war deployment.
There are a few hacks out there which seem to revolve around either multiple persistence.xml files and/or some strange-looking attempt at trying to reference the jar file using spring resource loaders (which didn't work for me).
My personal hack is to use spring resource loaders to resolve a resource which is in ALL the entity jars, parse out the URL jar reference and use a Spring persistence unit manager to inject these into the jar-file tag in the virtual persistence.xml
This is round-about way of doing it but avoids having multiple persistence.xml - which is technically invalid.
public class SpringPersistenceUnitManager extends DefaultPersistenceUnitManager implements ApplicationContextAware {
private final Logger log = LoggerFactory.getLogger(getClass());
private ApplicationContext ctx = null;
private String jarLocationPattern;
#Override
protected void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
super.postProcessPersistenceUnitInfo(pui);
try {
Resource[] resources = ctx.getResources("classpath*:applicationContext.xml");
for (Resource res : resources) {
String resJar = resolveJar(res.getURL());
if (!resJar.equals(pui.getPersistenceUnitRootUrl().toString())) {
log.info("Adding " + resJar + " to persistence context");
pui.addJarFileUrl(new URL(resJar));
}
}
}
catch (IOException e) {
log.error("error", e);
}
}
private String resolveJar(URL fileInJar) {
String path = fileInJar.getPath();
return path.substring(0, path.indexOf('!'));
}
and the spring context stuff:
<util:properties id="hibernate.properties" location="classpath:hibernate.properties" />
<bean id="persistenceUnitManager" class="com.rokksoft.blackice.util.SpringPersistenceUnitManager"
p:defaultDataSource-ref="jdbcDataSourcePool"
/>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" lazy-init="true"
p:persistenceUnitManager-ref="persistenceUnitManager"
p:persistenceUnitName="blackicePU"
p:dataSource-ref="jdbcDataSourcePool"
p:jpaProperties-ref="hibernate.properties">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
</bean>
You want to filter the jar names ideally though - 3rd party jar could have anything in.

No Persistence provider for EntityManager named

I have my persistence.xml with the same name using TopLink under the META-INF directory.
Then, I have my code calling it with:
EntityManagerFactory emfdb = Persistence.createEntityManagerFactory("agisdb");
Yet, I got the following error message:
2009-07-21 09:22:41,018 [main] ERROR - No Persistence provider for EntityManager named agisdb
javax.persistence.PersistenceException: No Persistence provider for EntityManager named agisdb
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:89)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:60)
Here is the persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="agisdb">
<class>com.agis.livedb.domain.AddressEntity</class>
<class>com.agis.livedb.domain.TrafficCameraEntity</class>
<class>com.agis.livedb.domain.TrafficPhotoEntity</class>
<class>com.agis.livedb.domain.TrafficReportEntity</class>
<properties>
<property name="toplink.jdbc.url" value="jdbc:mysql://localhost:3306/agisdb"/>
<property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="toplink.jdbc.user" value="root"/>
<property name="toplink.jdbc.password" value="password"/>
</properties>
</persistence-unit>
</persistence>
It should have been in the classpath. Yet, I got the above error.
Put the "hibernate-entitymanager.jar" in the classpath of application.
For newer versions, you should use "hibernate-core.jar" instead of the deprecated hibernate-entitymanager
If you are running through some IDE, like Eclipse: Project Properties -> Java Build Path -> Libraries.
Otherwise put it in the /lib of your application.
After <persistence-unit name="agisdb">, define the persistence provider name:
<provider>org.hibernate.ejb.HibernatePersistence</provider>
Make sure that the persistence.xml file is in the directory: <webroot>/WEB-INF/classes/META-INF
Faced the same issue and couldn't find solution for quite a long time. In my case it helped to replace
<provider>org.hibernate.ejb.HibernatePersistence</provider>
with
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
Took solution from here
I needed this in my pom.xml file:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.2.6.Final</version>
</dependency>
There is another point: If you face this problem within an Eclipse RCP environment, you might have to change the Factory generation from Persistence.createEntityManagerFactory to new PersistenceProvider().createEntityManagerFactory
see ECF for a detailed discussion on this.
Maybe you defined one provider like <provider>org.hibernate.ejb.HibernatePersistence</provider> but referencing another one in jar. That happened with me: my persistence.xml provider was openjpa but I was using eclipselink in my classpath.
Hope this help!
Quick advice:
check if persistence.xml is in your classpath
check if hibernate provider is in your classpath
With using JPA in standalone application (outside of JavaEE), a persistence provider needs to be specified somewhere. This can be done in two ways that I know of:
either add provider element into the persistence unit: <provider>org.hibernate.ejb.HibernatePersistence</provider> (as described in correct answere by Chris: https://stackoverflow.com/a/1285436/784594)
or provider for interface javax.persistence.spi.PersistenceProvider must be specified as a service, see here: http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html (this is usually included when you include hibernate,or another JPA implementation, into your classpath
In my case, I found out that due to maven misconfiguration, hibernate-entitymanager jar was not included as a dependency, even if it was a transient dependency of other module.
If you are using Eclipse make sure that exclusion pattern does not remove your persistence.xml from source folders on build path.
Go to Properties -> Java Build Path -> Source tab
Check your exclusion pattern which is located atMyProject/src/main/java -> Excluded: <your_pattern>tree node
Optionally, set it to Excluded: (None) by selecting the node and clicking Edit... button on the left.
I'm some years late to the party here but I hit the same exception while trying to get Hibernate 3.5.1 working with HSQLDB and a desktop JavaFX program. I got it to work with the help of this thread and a lot of trial and error. It seems you get this error for a whole variety of problems:
No Persistence provider for EntityManager named mick
I tried building the hibernate tutorial examples but because I was using Java 10 I wasn't able to get them to build and run easily. I gave up on that, not really wanting to waste time fixing its problems. Setting up a module-info.java file (Jigsaw) is another hairball many people haven't discovered yet.
Somewhat confusing is that these (below) were the only two files I needed in my build.gradle file. The Hibernate documentation isn't clear about exactly which Jars you need to include. Entity-manager was causing confusion and is no longer required in the latest Hibernate version, and neither is javax.persistence-api. Note, I'm using Java 10 here so I had to include the jaxb-api, to get around some xml-bind errors, as well as add an entry for the java persistence module in my module-info.java file.
Build.gradle
// https://mvnrepository.com/artifact/org.hibernate/hibernate-core
compile('org.hibernate:hibernate-core:5.3.1.Final')
// https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api
compile group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.0'
Module-info.java
// Used for HsqlDB - add the hibernate-core jar to build.gradle too
requires java.persistence;
With hibernate 5.3.1 you don't need to specify the provider, below, in your persistence.xml file. If one is not provided the Hibernate provider is chosen by default.
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
The persistence.xml file should be located in the correct directory so:
src/main/resources/META-INF/persistence.xml
Stepping through the hibernate source code in the Intellij debugger, where it checks for a dialect, also threw the exact same exception, because of a missing dialect property in the persistence.xml file. I added this (add the correct one for your DB type):
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
I still got the same exception after this, so stepping through the debugger again in Intellij revealed the test entity I was trying to persist (simple parent-child example) had missing annotations for the OneToMany, ManyToOne relationships. I fixed this and the exception went away and my entities were persisted ok.
Here's my full final persistence.xml:
<persistence 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://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="mick" transaction-type="RESOURCE_LOCAL">
<description>
Persistence unit for the JPA tutorial of the Hibernate Getting Started Guide
</description>
<!-- Provided in latest release of hibernate
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
-->
<class>com.micks.scenebuilderdemo.database.Parent</class>
<class>com.micks.scenebuilderdemo.database.Child</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbc.JDBCDriver"/>
<property name="javax.persistence.jdbc.url"
value="jdbc:hsqldb:file:./database/database;DB_CLOSE_DELAY=-1;MVCC=TRUE"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
</properties>
</persistence-unit>
</persistence>
I probably wasted about half a day on this gem. My advice would be to start very simple - a single test entity with one or two fields, as it seems like this exception can have many causes.
Corner case: if you are using m2Eclipse, it automatically puts in excludes on your resources folders. Then when you try to run tests inside eclipse, the subsequent absence of persistence.xml will produce this error.
Make sure you have created persistence.xml file under the 'src' folder. I created under the project folder and that was my problem.
If you're using Maven, it could be that it is not looking at the right place for the META-INF folder. Others have mentioned copying the folder, but another way that worked for me was to tell Maven where to look for it, using the <resources> tag. See: http://maven.apache.org/plugins/maven-resources-plugin/examples/resource-directory.html
It happenes when the entity manager is trying to point to many persistence units. Do the following steps:
open the related file in your editor (provided your project has been closed in your IDE)
delete all the persistence and entity manager related code
save the file
open the project in your IDE
now bind the db or table of your choice
I faced the same problem, but on EclipseLink version 2.5.0.
I solved my problem by adding yet another jar file which was necessarily (javax.persistence_2.1.0.v201304241213.jar.jar);
Jars needed:
- javax.persistence_2.1.0.v201304241213.jar
- eclipselink.jar
- jdbc.jar (depending on the database used).
I hope this helps.
I also had this error but the issue was the namespace uri in the persistence.xml.
I replaced http://xmlns.jcp.org/xml/ns/persistence to http://java.sun.com/xml/ns/persistence and the version 2.1 to 2.0.
It's now working.
You need to add the hibernate-entitymanager-x.jar in the classpath.
In Hibernate 4.x, if the jar is present, then no need to add the org.hibernate.ejb.HibernatePersistence in persistence.xml file.
In my case, previously I use idea to generate entity by database schema, and the persistence.xml is automatically generated in src/main/java/META-INF,and according to https://stackoverflow.com/a/23890419/10701129, I move it to src/main/resources/META-INF, also marked META-INF as source root. It works for me.
But just simply marking original META-INF(that is, src/main/java/META-INF) as source root, doesn't work, which confuses me.
and this is the structre:
The question has been answered already, but just wanted to post a tip that was holding me up. This exception was being thrown after previous errors. I was getting this:
property toplink.platform.class.name is deprecated, property toplink.target-database should be used instead.
Even though I had changed the persistence.xml to include the new property name:
<property name="toplink.target-database" value="oracle.toplink.platform.database.oracle.Oracle10Platform"/>
Following the message about the deprecated property name I was getting the same PersistenceException like above and a whole other string of exceptions. My tip: make sure to check the beginning of the exception sausage.
There seems to be a bug in Glassfish v2.1.1 where redeploys or undeploys and deploys are not updating the persistence.xml, which is being cached somewhere. I had to restart the server and then it worked.
In an OSGi-context, it's necessary to list your persistence units in the bundle's MANIFEST.MF, e.g.
JPA-PersistenceUnits: my-persistence-unit
Otherwise, the JPA-bundle won't know your bundle contains persistence units.
See http://wiki.eclipse.org/EclipseLink/Examples/OSGi/Developing_with_EclipseLink_OSGi_in_PDE .
You need the following jar files in the classpath:
antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
hibernate-commons-annotations-4.0.1.Final.jar
hibernate-core-4.0.1.Final.jar
hibernate-entitymanager.jar
hibernate-jpa-2.0-api-1.0.0.Final.jar
javassist-3.9.0.jar
jboss-logging-3.1.1.GA.jar
jta-1.1.jar
slf4j-api-1.5.8.jar
xxx-jdbc-driver.jar
I just copied the META-INF into src and worked!
Hibernate 5.2.5
Jar Files Required in the class path. This is within a required folder of Hibernate 5.2.5 Final release. It can be downloaded from http://hibernate.org/orm/downloads/
antlr-2.7.7
cdi-api-1.1
classmate-1.3.0
dom4j-1.6.1
el-api-2.2
geronimo-jta_1.1_spec-1.1.1
hibernate-commons-annotation-5.0.1.Final
hibernate-core-5.2.5.Final
hibernate-jpa-2.1-api-1.0.0.Final
jandex-2.0.3.Final
javassist-3.20.0-GA
javax.inject-1
jboss-interceptor-api_1.1_spec-1.0.0.Beta1
jboss-logging-3.3.0.Final
jsr250-api-1.0
Create an xml file "persistence.xml" in
YourProject/src/META-INF/persistence.xml
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence 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://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="sample">
<class>org.pramod.data.object.UserDetail</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/hibernate_project"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value="root"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="false"/>
<property name="hibernate.cache.use_second_level_cache" value="false"/>
<property name="hibernate.archive.autodetection" value="true"/>
</properties>
</persistence-unit>
please note down the information mentioned in the < persistance > tag and version should be 2.1.
please note the name < persistance-unit > tag, name is mentioned as "sample". This name needs to be used exactly same while loading your
EntityManagerFactor = Persistance.createEntityManagerFactory("sample");. "sample" can be changed as per your naming convention.
Now create a Entity class. with name as per my example UserDetail, in the package org.pramod.data.object
UserDetail.java
package org.pramod.data.object;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "user_detail")
public class UserDetail {
#Id
#Column(name="user_id")
private int id;
#Column(name="user_name")
private String userName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
#Override
public String toString() {
return "UserDetail [id=" + id + ", userName=" + userName + "]";
}
}
Now create a class with main method.
HibernateTest.java
package org.pramod.hibernate;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.pramod.data.object.UserDetail;
public class HibernateTest {
private static EntityManagerFactory entityManagerFactory;
public static void main(String[] args) {
UserDetail user = new UserDetail();
user.setId(1);
user.setUserName("Pramod Sharma");
try {
entityManagerFactory = Persistence.createEntityManagerFactory("sample");
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist( user );
entityManager.getTransaction().commit();
System.out.println("successfull");
entityManager.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output will be
UserDetail [id=1, userName=Pramod Sharma]
Hibernate: drop table if exists user_details
Hibernate: create table user_details (user_id integer not null, user_name varchar(255), primary key (user_id))
Hibernate: insert into user_details (user_name, user_id) values (?, ?)
successfull
If there are different names in Persistence.createEntityManagerFactory("JPAService") in different classes than you get the error. By refactoring it is possible to get different names which was in my case. In one class the auto-generated Persistence.createEntityManagerFactory("JPAService")in private void initComponents(), ContactsTable class differed from Persistence.createEntityManagerFactory("JPAServiceExtended") in DBManager class.
Mine got resolved by adding info in persistence.xml e.g. <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> and then making sure you have the library on classpath e.g. in Maven add dependency like
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.5.0</version>
</dependency>
Verify the peristent unit name
<persistence-unit name="com.myapp.model.jpa"
transaction-type="RESOURCE_LOCAL">
public static final String PERSISTENCE_UNIT_NAME = "com.myapp.model.jpa";
Persistence.createEntityManagerFactory(**PERSISTENCE_UNIT_NAME**);
In my case it was about mistake in two properties as below. When I changed them ‘No Persistence provider for EntityManager named’ disappered.
So you could try test connection with your properties to check if everything is correct.
<property name="javax.persistence.jdbc.url" value="...”/>
<property name="javax.persistence.jdbc.password" value="...”/>
Strange error, I was totally confused because of it.
Try also copying the persistence.xml manually to the folder <project root>\bin\META-INF. This fixed the problem in Eclipse Neon with EclipseLink 2.5.2 using a simple plug-in project.
Had the same issue, but this actually worked for me :
mvn install -e -Dmaven.repo.local=$WORKSPACE/.repository.
NB : The maven command above will reinstall all your project dependencies from scratch. Your console will be loaded with verbose logs due to the network request maven is making.
You have to use the absolute path of the file otherwise this will not work. Then with that path we build the file and pass it to the configuration.
#Throws(HibernateException::class)
fun getSessionFactory() : SessionFactory {
return Configuration()
.configure(getFile())
.buildSessionFactory()
}
private fun getFile(canonicalName: String): File {
val absolutePathCurrentModule = System.getProperty("user.dir")
val pathFromProjectRoot = absolutePathCurrentModule.dropLastWhile { it != '/' }
val absolutePathFromProjectRoot = "${pathFromProjectRoot}module-name/src/main/resources/$canonicalName"
println("Absolute Path of secret-hibernate.cfg.xml: $absolutePathFromProjectRoot")
return File(absolutePathFromProjectRoot)
}
GL
Source

Categories

Resources