Force JDO full initialization (with datanucleus lib) - java

I am working on warmup request to minimize my requests latency:
https://developers.google.com/appengine/docs/java/config/appconfig#Warmup_Requests
During that initialization I perform:
PersistenceManager pm = PMF.get().getPersistenceManager();
.. but from the logs I see it doesn't parse all the .jdo files where the class metadata are stored.
They are parsed only the first time I call this function "getObjectById" (for example) ..
Is it possible to force datanucleus to fully read all the metadata in order to be completely ready when the first getObjectById hits the PersistenceManager?
Thank you,
Michele
==============================================================================
UPDATE:
I tried with this persistence.xml file:
<persistence-unit name="my-transaction">
<mapping-file><path-to-first-jdo-file></mapping-file>
<mapping-file><path-to-second-jdo-file></mapping-file>
<mapping-file><path-to-third-jdo-file></mapping-file>
<properties>
<property name="datanucleus.NontransactionalRead" value="true"/>
<property name="datanucleus.NontransactionalWrite" value="true"/>
<property name="datanucleus.ConnectionURL" value="appengine"/>
</properties>
</persistence-unit>
that is associated with jdoconfig.xml:
<persistence-manager-factory name="my-transaction">
<property name="javax.jdo.PersistenceManagerFactoryClass" value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory" />
<property name="javax.jdo.option.ConnectionURL" value="appengine" />
<property name="javax.jdo.option.NontransactionalRead" value="true" />
<property name="javax.jdo.option.NontransactionalWrite" value="true" />
<property name="javax.jdo.option.RetainValues" value="true" />
<property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true" />
<property name="datanucleus.appengine.allowMultipleRelationsOfSameType" value="true" />
<property name="datanucleus.appengine.datastoreReadConsistency" value="STRONG" />
<property name="datanucleus.appengine.ignorableMetaDataBehavior" value="ERROR" />
<property name="javax.jdo.option.Multithreaded" value="true"/>
<property name="javax.jdo.option.Optimistic" value="false" />
</persistence-manager-factory>
.. but I continue to see in the logs the previuos behaviour. During loading request:
org.datanucleus.store.types.TypeManager addJavaType: Adding support for Java type <class>
.. and during the first request that really needs a class mapping (getObjectById for example):
org.datanucleus.metadata.xml.MetaDataParser parseMetaDataStream: Parsing MetaData file <class>.jdo
So the first request that retrieves the object is longer than the following ones because it needs to parse the XML file.
What's wrong?
I am using datanucleus 1.1.5
Thank you

Specify a "persistence.xml" defining all classes/mapping files. This is then read/loaded at startup.
Also ancient version of DataNucleus aren't supported, so use the newer version of the GAE JPA plugin with DataNucleus v3.x

Related

Issue setting FlushMode.COMMIT in Quarkus Hibernate ORM

Issue I have using Quarkus+Hibernate:
For performance purposes we need to set FlushMode as COMMIT in our hibernate Session.
And we realized that this property configuration is not available in application.properties parameters, see: https://quarkus.io/guides/hibernate-orm#hibernate-configuration-properties
So, we took the path to setting up the configuration with persistence.xml file: https://quarkus.io/guides/hibernate-orm#persistence-xml
...
<persistence-unit name="SomethingPU" transaction-type="JTA">
<description>Something Entities</description>
<properties>
<!-- Connection specific -->
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServer2012Dialect" />
<!-- cache properties -->
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_minimal_puts" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<!-- multitenancy -->
<property name="hibernate.multiTenancy" value="DATABASE" />
<!-- scan for annotated classes -->
<property name="hibernate.archive.autodetection" value="class"/>
<!-- performance tunning -->
<property name="org.hibernate.flushMode" value="COMMIT" />
<property name="hibernate.jdbc.batch_size" value="100" />
<property name="hibernate.jdbc.fetch_size" value="400" />
<property name="hibernate.order_updates" value="true" />
<property name="hibernate.order_inserts" value="true" />
<property name="hibernate.max_fetch_depth" value="1" />
</properties>
</persistence-unit>
When we start our service everything's fine, the properties are loaded into the Session, except for "org.hibernate.flushMode" parameter.
Debugging the code we see this behaviour:
when the service starts, Quarkus executes the Recorder: io.quarkus.hibernate.orm.runtime.HibernateOrmRecorder
this class initialize org.hibernate.Session using the class: io.quarkus.hibernate.orm.runtime.TransactionSessions
TransactionsSessions mantains a Map of io.quarkus.hibernate.orm.runtime.session.TransactionScopedSession
so, when TransactionScopedSession acquires the Session, it executes:
TransactionScopedSession.aquireSession
line 88:
Session newSession = jtaSessionOpener.openSession();
which ends calling JTASessionOpener.createOptions method:
return sessionFactory.withOptions()
.autoClose(true) // .owner() is deprecated as well, so it looks like we need to rely on deprecated code...
.connectionHandlingMode(
PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_RELEASE_BEFORE_TRANSACTION_COMPLETION)
.flushMode(FlushMode.ALWAYS);
Here JTASessionOpener is setting flushMode as ALWAYS
calling the method: SessionFactoryImpl.flushMode
When org.hibernate.internal.SessionImpl is created
org.hibernate.internal.SessionImpl.SessionImpl(SessionFactoryImpl, SessionCreationOptions)
line 266:
if ( getHibernateFlushMode() == null ) {
final FlushMode initialMode;
if ( this.properties == null ) {
initialMode = fastSessionServices.initialSessionFlushMode;
}
...
The method getHibernateFlushMode() is returning FlushMode.ALWAYS
And because of this, the parameter "org.hibernate.flushMode" from persistence.xml is never setted.
We fix this issue setting the flushMode directly in javax.persistence.EntityManager instance, before we use it in any query or DB operation.
But, my questions are:
is there a way to bypass JTASessionOpener or use another logic? can it be considered as a bug or issue to solve?
is there a better way (than our solution) to fix this issue?
is there a plan to add the property "org.hibernate.flushMode" in Quarkus Hibernate ORM extension?, so we can set this in application.properties
--
Hope the description is clear.

Weblogic 12 get eclipse error when tried to deploy

When i tried to deploy an application in weblogic, he give-me the follow exception:
Substituted for missing class Exception [EclipseLink-7298] (Eclipse
Persistence Services - 2.6.5.v20170607-b3d05bd) -
org.eclipse.persistence.exceptions.ValidationException Exception
Description: The mapping [associated] from the embedded ID class
[class br.com.webproj.web.model.associated.pk.AssmaintainPK] is an
invalid mapping for this class. An embeddable class that is used with
an embedded ID specification (attribute [AssmaintainPK] from the
source [class br.com.webproj.web.model.associated.AssMaintain]) can
only contain basic mappings. Either remove the non basic mapping or
change the embedded ID specification on the source to be embedded.
In my persistence.xml i have:
<?xml version="1.0" encoding="UTF-8"?>
<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_2_0.xsd"
version="2.0">
<persistence-unit name="Web_PU">
<jta-data-source>JDBC/WEB</jta-data-source>
<jar-file>web-Model.jar</jar-file>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.hbm2ddl.auto" value="none" />
<property name="hibernate.show_sql" value="false" />
<!-- Cache Enabled -->
<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.JndiInfinispanRegionFactory" />
<property name="hibernate.cache.infinispan.cachemanager"
value="java:jboss/infinispan/container/hibernate" />
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup" />
<property name="hibernate.cache.infinispan.statistics"
value="true" />
<!-- I TRIED INCLUDING THIS, BUT NOT SOLVE -->
<property name="eclipselink.exclude-eclipselink-orm"
value="false" />
<property name="eclipselink.orm.throw.exceptions"
value="false" />
<property name="eclipselink.orm.validate.schema"
value="false" />
</properties>
</persistence-unit>
</persistence>
I think this error occurs because the weblogic use the eclipse link, and the project an other version of jpa. But the error is in a jar included in project and i cant change and see the code. If the problem is this, what i can do to dont use the eclipse link of weblogic (obs: in JBoss the project runs normally).

configure max pool size hikaricp hibernate JPA

I'm trying to use hibernate jpa and hikaricp for the CP.
But I have an issue that I dont understand, so either my config is bad ... or I do have something else.
this is the config In have in my persistence.xml file :
<properties>
<!-- SQL -->
<property name="hibernate.dialect" value="org.hibernate.spatial.dialect.mysql.MySQLSpatialDialect" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
<!-- HikariCP -->
<property name="hibernate.connection.provider_class" value="com.zaxxer.hikari.hibernate.HikariConnectionProvider"/>
<property name="hibernate.hikari.driverClassName" value="com.mysql.jdbc.Driver" />
<property name="hibernate.hikari.minimumIdle" value="5"/>
<property name="hibernate.hikari.maximumPoolSize" value="30"/>
<property name="hibernate.hikari.maxLifetime" value="150000"/>
<property name="hibernate.hikari.dataSource.user" value="user" />
<property name="hibernate.hikari.dataSource.password" value="password" />
<property name="hibernate.hikari.jdbcUrl"
value="jdbc:mysql://server:3306" />
</properties>
Still I'm having 100+ connections on the database. I thought that using maximumPoolSize it would have limit my number of connections. Is my configuration OK, based on my research it seems ok to me, but before trying to debug elsewhere I want to make sure it is.
Thanks
You must be missing the hibernate-hikari module jar on your classpath. This module is necessary to integrate hibernate with HikariCP
Here is the official documentation

How to fine-tune a JPA/JAX-RS application

I've developed a JAX-RS JSON API in Wildfly/RESTeasy with a JPA/Hibernate backend and I have serious database access problems.
For example, suddenly the application stop responding and the logs show a bunch of:
ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (EJB default - 4) IJ031012: Unable to obtain lock in 60 seconds: org.jboss.jca.adapters.jdbc.local.LocalManagedConnection
INFO [org.jboss.jca.core.connectionmanager.listener.TxConnectionListener] IJ000302: Unregistered handle that was not registered: org.jboss.jca.adapters.jdbc.jdk7.WrappedConnectionJDK7
WARN [org.jboss.jca.core.connectionmanager.pool.strategy.OnePool] IJ000609: Attempt to return connection twice: org.jboss.jca.core.connectionmanager.listener.TxConnectionListener
WARN [org.jboss.jca.adapters.jdbc.local.LocalManagedConnectionFactory] (default task-9) IJ030020: Detected queued threads during cleanup
ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (ForkJoinPool.commonPool-worker-0) IJ031041: Connection handle has been closed and is unusable
ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (ForkJoinPool.commonPool-worker-1) IJ031050: The result set is closed
I think this is due to multiple access by different users (say 15, 20 users simultaneously), since with one/two users this not happens.
I'm on Hibernate 5.1 and Wildfly 10, and SQL Server 2014. It is a vanilla installation, with no tweaks or custom configurations. How can I fine-tune the infrastructure to avoid these issues?
The problem was related to the REST services being #Stateless and therefore opening transactions on each request. The solution was to inject #Stateless DAOs into the REST services: no more locking issues.
Use HikariCP connection pool.
Based on your traffic configure no of connections in the connection pool as well as in database.
In the connection pool there is option to maintain some amount connections available all the time. And also set the connection isolation type as after commit only.
Below is the sample of it,
<persistence-unit name="sample" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<!-- provider -->
<property name="hibernate.connection.provider_class" value="com.xo.web.persistence.XOHikariCPConnectionProvider"/>
<!-- Hibernate properties -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.archive.autodetection" value="hbm" />
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="show_sql" value="false"/>
<property name="hibernate.connection.release_mode" value="after_transaction"/>
<property name="hibernate.connection.autocommit" value="false"/>
<property name="hibernate.connection.isolation" value="2"/>
<property name="hibernate.ejb.interceptor" value="com.xo.web.persistence.intercept.XoEntityInterceptor"/>
<property name="hibernate.jdbc.batch_size" value="100"/>
<property name="hibernate.order_inserts" value="true"/>
<property name="hibernate.order_updates" value="true"/>
<!-- Hikari settings -->
<property name="maximumPoolSize" value="80" />
<property name="autoCommit" value="false" />
<property name="minimumPoolSize" value="20" />
<property name="idleTimeout" value="60000" />
<property name="maxLifetime" value="600000" />
<property name="connectionInitSql" value="select 1" />
<property name="connectionTimeout" value="1000" />
<property name="validationTimeout" value="1000" />
<property name="cachePrepStmts" value="true" />
<property name="prepStmtCacheSize" value="250" />
<property name="prepStmtCacheSqlLimit" value="2048" />
</properties>
</persistence-unit>

SSL with EclipseLink JPA

Is it possible to make JPA use SSL for it's connections. I don't know very much about JPA, so I can't provide many details about what version and provider I'm using, but here is a stripped version of my persistence.xml file. Is there a property you can add that makes it use secure connections?
<?xml version="1.0" encoding="UTF-8" ?>
<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"
version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="MY_PERSISTENCE_UNIT" transaction-type="RESOURCE_LOCAL">
<!-- declare class entities here -->
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://URL_TO_SERVER" />
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.user" value="USERNAME" />
<property name="javax.persistence.jdbc.password" value="PASSWORD" />
<!-- Optimize database writes to use batching. -->
<property name="eclipselink.jdbc.batch-writing" value="JDBC" />
<!-- Avoids flush being triggered before every query execution. -->
<property name="eclipselink.persistence-context.flush-mode"
value="COMMIT" />
<!-- Configure connection pool. -->
<property name="eclipselink.jdbc.connections.initial" value="1" />
<property name="eclipselink.jdbc.connections.min" value="64" />
<property name="eclipselink.jdbc.connections.max" value="64" />
<!-- Timeout for connection. -->
<property name="eclipselink.jdbc.timeout" value="10" />
<!-- Configure cache size. -->
<property name="eclipselink.cache.size.default" value="1000" />
<!-- Configure database to be created on startup if not already existing.-->
<property name="eclipselink.ddl-generation" value="create-tables" />
<!-- Configure simple SQL logging for demonstration. -->
<property name="eclipselink.logging.level" value="FINE" />
<property name="eclipselink.logging.thread" value="false" />
<property name="eclipselink.logging.session" value="false" />
<property name="eclipselink.logging.exceptions" value="false" />
<property name="eclipselink.logging.timestamp" value="false" />
</properties>
</persistence-unit>
It is not anything JPA specific, just about adding arguments to JDBC connection String. Assuming that everything else is correctly set, then adding this should be enough:
?useSSL=true&requireSSL=true
If SSL connection in general is not working, then this page provides more information: MySQL 20.3.4.5. Connecting Securely Using SSL
I found this was useful in EclipseLink 2.5.0 to pass properties through to the JDBC driver:
<property name="eclipselink.jdbc.property.my_property_name" value="my_value" />
This is driver specific, but in your case it would be:
<property name="eclipselink.jdbc.property.useSSL" value="true" />
<property name="eclipselink.jdbc.property.requireSSL" value="true" />

Categories

Resources