We use Tomee 1.7.1 jaxrs with multiple datasources and applications.
For example:
App1 persistance.xml
<persistence-unit name="DS1_PU" transaction-type="JTA">
<jta-data-source>DS1</jta-data-source>
...
</persistence-unit>
App2 persistance.xml
<persistence-unit name="DS2_PU" transaction-type="JTA">
<jta-data-source>DS2</jta-data-source>
...
</persistence-unit>
tomee.xml
<Resource id="DS1" type="DataSource">
JdbcDriver org.postgresql.Driver
JdbcUrl jdbc:postgresql://localhost:5432/DS1
UserName postgres
Password 123
JtaManaged true
ValidationQuery select 1
TestOnBorrow true
</Resource>
<Resource id="DS2" type="DataSource">
JdbcDriver org.postgresql.Driver
JdbcUrl jdbc:postgresql://localhost:5432/DS2
UserName postgres
Password 123
JtaManaged true
ValidationQuery select 1
TestOnBorrow true
</Resource>
Deployment log:
INFORMATION: Adjusting PersistenceUnit DS1_PU to Resource ID 'DS1NonJta' from 'null'
INFORMATION: Adjusting PersistenceUnit DS2_PU to Resource ID 'DS2NonJta' from 'null'
Problem:
When I make a typo in a persistance.xml, f.e.
<persistence-unit name="DS2_PU" transaction-type="JTA">
<jta-data-source>DS_WRONG</jta-data-source>
...
</persistence-unit>
app still deployes but use wrong data source:
INFORMATION: Adjusting PersistenceUnit DS2_PU to Resource ID 'DS1NonJta' from 'null'
It seems that openejb takes first founded data source.
Can I disable this "feature"?
Related
What I did:
download and extract the latest openjpa release (3.0.0)
download the mariadb jdbc driver jar and copy it to the same directory where openjpa-all-3.0.0.jar is located
inside the same directory, create a subdirectory META_INF and a file META-INF/persistence.xml with the following contents:
<?xml version="1.0"?>
<persistence version="1.0">
<persistence-unit name="openjpa">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<properties>
<property name="openjpa.ConnectionURL" value="jdbc:mariadb://localhost:3306/databasename"/>
<property name="openjpa.ConnectionDriverName" value="org.mariadb.jdbc.Driver"/>
<property name="openjpa.ConnectionUserName" value="dbuser"/>
<property name="openjpa.ConnectionPassword" value="dbpassword"/>
<property name="openjpa.DynamicEnhancementAgent" value="false"/>
<property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
<property name="openjpa.Log" value="SQL=TRACE"/>
<property name="openjpa.ConnectionFactoryProperties" value="PrettyPrint=true, PrettyPrintLineLength=120, PrintParameters=true, MaxActive=10, MaxIdle=5, MinIdle=2, MaxWait=60000"/>
</properties>
</persistence-unit>
create an empty directory src as a sub-directory of where the openjpa and mariadb driver jars are
ran the following command:
java -cp ./:openjpa-all-3.0.0.jar:mariadb-java-client-2.4.0.jar:openjpa-all-3.0.0.jar org.apache.openjpa.jdbc.meta.ReverseMappingTool -pkg some.package -d ./src
Instead of getting any kind of output, or an error related to generation, I get:
8 INFO [main] openjpa.Tool - The reverse mapping tool will run on the database. The tool is gathering schema information; this process may take some time. Enable the org.apache.openjpa.jdbc.Schema logging category to see messages about schema data.
Exception in thread "main" <openjpa-3.0.0-r422266:1833209 fatal user error> org.apache.openjpa.util.UserException: The persistence provider is attempting to use properties in the persistence.xml file to resolve the data source. A Java Database Connectivity (JDBC) driver or data source class name must be specified in the openjpa.ConnectionDriverName or javax.persistence.jdbc.driver property. The following properties are available in the configuration: "org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl#f248234b".
at org.apache.openjpa.jdbc.schema.DataSourceFactory.newDataSource(DataSourceFactory.java:71)
at org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl.createConnectionFactory(JDBCConfigurationImpl.java:850)
at org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl.getConnectionFactory(JDBCConfigurationImpl.java:733)
at org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl.getDataSource(JDBCConfigurationImpl.java:879)
at org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl.getDataSource2(JDBCConfigurationImpl.java:921)
at org.apache.openjpa.jdbc.schema.SchemaGenerator.<init>(SchemaGenerator.java:86)
at org.apache.openjpa.jdbc.meta.ReverseMappingTool.run(ReverseMappingTool.java:2027)
at org.apache.openjpa.jdbc.meta.ReverseMappingTool.run(ReverseMappingTool.java:2005)
at org.apache.openjpa.jdbc.meta.ReverseMappingTool.run(ReverseMappingTool.java:1882)
at org.apache.openjpa.jdbc.meta.ReverseMappingTool$1.run(ReverseMappingTool.java:1863)
at org.apache.openjpa.lib.conf.Configurations.launchRunnable(Configurations.java:762)
at org.apache.openjpa.lib.conf.Configurations.runAgainstAllAnchors(Configurations.java:747)
at org.apache.openjpa.jdbc.meta.ReverseMappingTool.main(ReverseMappingTool.java:1858)
What am I doing wrong?
I tried variations of this, by adding -p persistence.xml#openjpa, -p #openjpa and -connectionDriverName org.mariadb.jdbc.Driver to the command line, but it made no difference.
I am trying to use MongoDB Atlas M0 (Free Tier) for my JAVA EE application, now I am using:
Local MongoDB database (v4.0.4)
Hibernate Core "hibernate-core 5.3.6.Final"
Hibernate OGM "hibernate-ogm-mongodb 5.3.1.Final"
Java application server WildFly 15.0.0.Final.
With a local database a pair MongoDB and Hibernate OGM works like a charm, but when I tried to connect Hibernate with Mongo Atlas on free tier to test cloud database, I am was not able to have a working connection, because mongodb driver throws an exception com.mongodb.MongoSocketReadException: Prematurely reached end of stream
I will provide two versions of my persistence.xml, first is working fine with localhost and second is what I used to connect to cloud.
working localhost version:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<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_2.xsd"
version="2.2">
<!-- ### MongoDB HIBERNATE OGM PERSISTENCE UNIT ### -->
<persistence-unit name="PersistenceUnitNoSQL" transaction-type="JTA">
<provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
<class>org.companyname.model.UserEntity</class>
<class>org.companyname.model.ItemEntity</class>
<properties>
<property name="hibernate.ogm.datastore.provider" value="mongodb"/>
<property name="hibernate.ogm.datastore.host" value="localhost:27017"/>
<property name="hibernate.ogm.datastore.database" value="databasename"/>
<property name="hibernate.ogm.datastore.create_database" value="true"/>
</properties>
</persistence-unit>
</persistence>
not working atlas cloud version:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<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_2.xsd"
version="2.2">
<!-- ### MongoDB HIBERNATE OGM PERSISTENCE UNIT ### -->
<persistence-unit name="PersistenceUnitNoSQL" transaction-type="JTA">
<provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
<class>org.companyname.model.UserEntity</class>
<class>org.companyname.model.ItemEntity</class>
<properties>
<property name="hibernate.ogm.datastore.provider" value="mongodb"/>
<property name="hibernate.ogm.datastore.host" value="cluster0-clustername-shard-00-00-raa4n.mongodb.net:27017,cluster0-clustername-shard-00-01-raa4n.mongodb.net:27017,cluster0-clustername-shard-00-02-raa4n.mongodb.net:27017"/>
<property name="hibernate.ogm.datastore.database" value="databasename"/>
<property name="hibernate.ogm.datastore.create_database" value="true"/>
<property name="hibernate.ogm.datastore.username" value="atlas-user-name"/>
<property name="hibernate.ogm.datastore.password" value="atlas-user-password"/>
<property name="hibernate.ogm.mongodb.authentication_mechanism" value="SCRAM_SHA_1"/>
</properties>
</persistence-unit>
</persistence>
Like a host I used replica sets URIs from "standard connection string" from helping window in the Atlas account, because with "short SRV connection string" Hibernate throws org.hibernate.service.spi.ServiceException: OGM000072: Unable to configure datastore provider, so I think there is no support of this type of connection yet.
So with this last persistence.xml configuration I had following error:
20:02:01,094 INFO [org.mongodb.driver.cluster] (ServerService Thread Pool -- 78) Cluster description not yet available. Waiting for 30000 ms before timing out
20:02:01,175 INFO [org.mongodb.driver.cluster] (cluster-ClusterId{value='5c5497a97aea6111622c7540', description='null'}-cluster0-clustername-shard-00-02-raa4n.mongodb.net:27017)
Exception in monitor thread while connecting to server cluster0-clustername-shard-00-02-raa4n.mongodb.net:27017: com.mongodb.MongoSocketReadException: Prematurely reached end of stream
at com.mongodb.internal.connection.SocketStream.read(SocketStream.java:112)
at com.mongodb.internal.connection.InternalStreamConnection.receiveResponseBuffers(InternalStreamConnection.java:570)
at com.mongodb.internal.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.java:441)
at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:295)
at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:255)
at com.mongodb.internal.connection.CommandHelper.sendAndReceive(CommandHelper.java:83)
at com.mongodb.internal.connection.CommandHelper.executeCommand(CommandHelper.java:33)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initializeConnectionDescription(InternalStreamConnectionInitializer.java:106)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initialize(InternalStreamConnectionInitializer.java:63)
at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:127)
at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:117)
at java.lang.Thread.run(Thread.java:748)
Hibernate tries to connect to each shard (00-00, 00-01, 00-02), but with all throws this exception.
What I tried to do to fix the problem:
using mongo-java-driver version 3.9.1 instead of Hibernate 3.6.3 built-in, but both drivers work with the same problem
my IP is added (my app is deployed from my laptop) to my atlas account IP Whitelist
I am able to connect fine to cluster from Mongo Shell and MongoDB Compass
I had a doubts about "hibernate.ogm.mongodb.authentication_mechanism", but "SCRAM_SHA_1" and "BEST" didn't worked for me
and finally I tried to make a connection to the cluster from Java directly (without Hibernate)
with
MongoClient mongoClient = MongoClients.create("mongodb+srv://atlas-user-name:atlas-user-password#cluster0-clustername-raa4n.mongodb.net/test?retryWrites=true");
or
MongoClient mongoClient = MongoClients.create("mongodb://atlas-user-name:atlas-user-password#cluster0-clustername-shard-00-00-raa4n.mongodb.net:27017,cluster0-clustername-shard-00-01-raa4n.mongodb.net:27017,cluster0-clustername-shard-00-02-raa4n.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-clustername-shard-0&authSource=admin&retryWrites=true");
and both cases worked fine, I was able to make a connection and to use the database without problems.
So my problem is why Hibernate throws this kind of exception?
It's possible that something is not right in the way Hibernate OGM creates the client.
I think the easier way to check this now for you is to override the MongoDBDatastoreProvider and provide an initialized MongoClient.
You can do this by extending MongoDBDatastoreProvider and overriding the method createMongoClient. Something like:
package org.myprojects;
import org.hibernate.ogm.datastore.mongodb.impl.MongoDBDatastoreProvider;
public class MYCustomMongoDBDatastoreProvider extends MongoDBDatastoreProvider {
#Override
protected MongoClient createMongoClient(MongoDBConfiguration config) {
return MongoClients.create(...);
}
}
then use the property OgmProperties.DATASTORE_PROVIDER to use your datastore provider:
hibernate.ogm.datastore.provider = org.myprojects.MYCustomMongoDBDatastoreProvider
In this example I'm setting it in the hibernate.properties file but you can set it where it makes more sense for your project.
EDIT: Additional explanations about the error.
I think the problems is that we are not using the factory to create the mongo client.
EDIT 2: The problem might be caused by a lack of support for SSL.
An issue has been created and contains more information
Got the same problem. I, additionally, enabled SSL and the connection was success:
<property name="hibernate.ogm.mongodb.driver.sslEnabled" value="true"/>
My Java EE application cannot find tables. I am using WildFly (as the application server) and H2 (as the DB, in the embedded mode).
The error is:
org.h2.jdbc.JdbcSQLException: Table "MY_TABLE" not found
Look at my table creation:
create table "MY_TABLE" (
-- ...
);
See how my entity is defined:
#Entity
#Table(name = "MY_TABLE")
public class MyTable {
// ...
}
This is how I call JPA (this causes the exception):
#PersistenceContext
private EntityManager entityManager;
// ...
entityManager.find(MyTable.class, 1);
My persistence.xml is:
<persistence-unit name="myapp" transaction-type="JTA">
<jta-data-source>java:jboss/datasources/myappDS</jta-data-source>
</persistence-unit>
And the standalone.xml in my WildFly:
<datasource jndi-name="java:jboss/datasources/myappDS" pool-name="myappDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:~/myapp;SCHEMA=PUBLIC</connection-url>
<driver>h2</driver>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
Everything looks good so why the exception? Do I need to flush something? Or set schema somewhere?
If I configure another datasource (having the same DB structure) in WildFly (for example Postgres), everything works fine. That would mean that the datasource configuration is the place causing the error.
(Yes, I am totally sure the DB is not empty and the connection URL is correct as I have tried it from an SQL client.)
Are you running the application as a different user than you are testing to connect with? In that case the the ~ in the connection path will resolve to different home folders, and thus different databases.
Otherwise I would suggest connecting with the Shell in the h2 jar file and run show tables to verify that the table exists and with the correct casing. Start the shell by running:
java -cp h2*.jar org.h2.tools.Shell
Where do you store your script for the table creation? Is it in classpath of the application?
In my test setup I let hibernate generate the tables on startup (and dropping it on shutdown) and using an import.sql script for the test-data generation, which is in the folder src/main/resources.
<persistence-unit name="myapp" transaction-type="JTA">
<jta-data-source>java:jboss/datasources/myappDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
</persistence-unit>
I have problem with configuring JPA in Websphere Liberty Profile. EclipseLink which is default provider in WAS with feature jpa-2.1 don't read the properties from created in server.xml DataSource. I've tried to get connection from this data source without JPA and this connection was succesfull, i had access to database. But when i use JPA and then create EntityManagerFactory from my PerstistenceUnit i get exception which in my opinion means that i didn't give required parameters such as url, username and password. I tested that WAS recognize EclipseLink provider, but now i don't know what can I do with this problem. Google haven't helped me.
Persistence.xml
<persistence version="1.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_1_0.xsd">
<persistence-unit name="test-unit" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:comp/env/jdbc/PostgreDS</jta-data-source>
<properties>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.ddl-generation.output-mode"
value="database" />
</properties>
</persistence-unit>
server.xml(only part with my setting of JDBC and DS)
<jdbcDriver id="myJDBCDriver" libraryRef="JDBCLib" javax.sql.XADataSource="org.postgresql.xa.PGXADataSource" >
</jdbcDriver>
<library id="JDBCLib" name="PostgreLib">
<file name="/home/hubert/JavaLibs/postgresql-9.4-1206-jdbc41.jar" id="JDBC_JAR"></file>
</library>
<dataSource id="PostrgreConnection" jdbcDriverRef="myJDBCDriver" jndiName="jdbc/PostgreDS" type="javax.sql.XADataSource">
<properties URL="jdbc:postgresql://localhost/GotSpotDB" databaseName="GotSpotDB" password="testtest" portNumber="5432" serverName="localhost" user="GotSpotAdmin"/>
</dataSource>
Logs
[ERROR ] CWWJP9992E: Exception [EclipseLink-4021] (Eclipse Persistence Services - 2.6.1.WAS-v20160106-a06c2b3): org.eclipse.persistence.exceptions.DatabaseException
Exception Description: Unable to acquire a connection from driver [null], user [null] and URL [null]. Verify that you have set the expected driver class and URL. Check your login, persistence.xml or sessions.xml resource. The jdbc.driver property should be set to a class that is compatible with your database platform
[ERROR ] SRVE0777E: Exception thrown by application class 'org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy:837'
javax.persistence.PersistenceException: Exception [EclipseLink-4021] (Eclipse Persistence Services - 2.6.1.WAS-v20160106-a06c2b3): org.eclipse.persistence.exceptions.DatabaseException
Exception Description: Unable to acquire a connection from driver [null], user [null] and URL [null]. Verify that you have set the expected driver class and URL. Check your login, persistence.xml or sessions.xml resource. The jdbc.driver property should be set to a class that is compatible with your database platform
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:837)
at [internal classes]
at pl.almost.done.TestServlet.doGet(TestServlet.java:52)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at [internal classes]
Caused by: Exception [EclipseLink-4021] (Eclipse Persistence Services - 2.6.1.WAS-v20160106-a06c2b3): org.eclipse.persistence.exceptions.DatabaseException
Exception Description: Unable to acquire a connection from driver [null], user [null] and URL [null]. Verify that you have set the expected driver class and URL. Check your login, persistence.xml or sessions.xml resource. The jdbc.driver property should be set to a class that is compatible with your database platform
at org.eclipse.persistence.exceptions.DatabaseException.unableToAcquireConnectionFromDriverException(DatabaseException.java:383)
... 4 more
I am having problems connecting to 2 persistence units from within the same transaction using following tech stack,
WLS 10.3.x, Eclipselink 2.1, Oracle 11g JDBC driver, Informix 10 JDBC driver
Using inputs from this SO post I made the oracle datasource XA compliant and the Informix ds "Emulate 2-phase commit" and things started to work. However, now I am getting a strange problem.
I am using standalone java client to invoke my ejb 3 SLSB which in turn invokes the JPA entities. The problem I am facing is it works the first time, the second time it does not throw any exception but does not update the data in either databases and the 3rd time it throws an exception stating "Transaction has already been committed" as if the application server JTA transaction manager is holding on to the original transaction context. Please note these 3 invocations are separate and sequential wherein every invocations completes with the client exiting the client process. The problem is very consistent and happens in the exact same sequence every time I restart the app server.
Appreciate any input!
<persistence-unit name="TopLinkDB" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/oracleDS</jta-data-source>
<class>com.home.domain.Property</class>
<properties>
<property name="eclipselink.target-server" value="WebLogic_10" />
</properties>
</persistence-unit>
<persistence-unit name="TopLinkINFO" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/infoDS</jta-data-source>
<class>com.home.domain.GlobalNumber</class>
<properties>
<property name="eclipselink.target-server" value="WebLogic_10" />
</properties>
</persistence-unit>