I have a perfectly working application client deployed to a GlassFish v2 server inside an ear with some EJBs, Entities, etc. I'm using eclipselink.
Currently I have in my persistence.xml:
<persistence-unit name="mysource">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/mysource</jta-data-source>
<class>entities.one</class>
<class>entities.two</class>
...
<properties>
<property name="eclipselink.target-server" value="SunAS9"/>
<property name="eclipselink.logging.level" value="FINE"/>
</properties>
</persistence-unit>
And this works fine when I inject the EntityManager into the EJB:
#PersistenceContext(unitName="mysource")
private EntityManager em;
Now I have a requirement to dynamically switch persistence units/databases.
I figure I can get an EntityManager programatically:
em = Persistence.createEntityManagerFactory("mysource").createEntityManager();
but I get the following error:
Unable to acquire a connection from driver [null], user [null] and URL [null]
Even "overriding" javax.persistence.jtaDataSource" to "jdbc/mysource" in a Map and calling createEntityManagerFactory("mysource", map) doesn't make a difference.
What am I missing?
You are trying to circumvent the container with creating an entity manager programmatically and this means you'll most probably create a non-JTA data source (as it's outside the container, the transaction type should be RESOURCE_LOCAL), thus your original config is useless.
Try injecting an entity manager with a different unitName property or create a RESOURCE_LOCAL transaction type persistence unit.
Related
Exception is thrown when trying to Insert/Update/Delete with executeUpdate(). Select query works fine.I have tried all the suggestions from previous similar error mentioned in stack-overflow. Appreciate any guidance.
Environment : Websphere Liberty : 17.0.0.2, Eclipselink 2.6.4, JPA 2.1
Features enabled on Liberty server
<featureManager>
<feature>adminCenter-1.0</feature>
<feature>beanValidation-1.1</feature>
<feature>cdi-1.2</feature>
<feature>concurrent-1.0</feature>
<feature>ejbLite-3.2</feature>
<feature>el-3.0</feature>
<feature>jsf-2.2</feature>
<feature>jsp-2.3</feature>
<feature>localConnector-1.0</feature>
<feature>servlet-3.1</feature>
<feature>jpa-2.1</feature>
<!--The following features are available in Liberty base and above. -->
<feature>jaxb-2.2</feature>
</featureManager>
Peristence.xml
<?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="BlueeCron" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/BlueeUPMDataSource</jta-data-source>
<mapping-file>META-INF/queries.xml</mapping-file>
<class>com.bcbsnc.providers.models.BlueEReqst</class>
<class>com.bcbsnc.providers.models.BlueERespn</class>
<properties>
<property name="eclipselink.logging.level" value="ALL" />
<property name="eclipselink.logging.level.sql" value="FINE" />
<property name="eclipselink.logging.parameters" value="true" />
</properties>
</persistence-unit>
#Stateless
#Repository("emJPADao")
public class JPADao {
EntityManager entityManager = Persistence.createEntityManagerFactory("BlueeCron").createEntityManager();
public Integer purgeBxTables() {
Integer rowsDeleted = 0;
try {
Integer noOfDays = Integer.parseInt(this.getConfigurationData("PurgeBXTablesPeriod"));
rowsDeleted = entityManager.createNamedQuery("PURGE_BX_TABLES").setParameter("noOfDays", getTimeStamp(noOfDays, false)).executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(entityManager.isOpen())
entityManager.close();
}
}
}
Logs at server startup
Launching defaultServer (WebSphere Application Server 17.0.0.2/wlp-1.0.17.cl170220170523-1818) on IBM J9 VM, version pwa6480sr4fp5-20170421_01 (SR4 FP5) (en_US)
[AUDIT ] CWWKF0012I: The server installed the following features: [jsp-2.3, ejbLite-3.2, servlet-3.1, jsf-2.2, beanValidation-1.1, ssl-1.0, jndi-1.0, jca-1.7, jdbc-4.2, localConnector-1.0, appSecurity-2.0, jaxrs-2.0, restConnector-1.0, el-3.0, jaxrsClient-2.0, concurrent-1.0, wmqJmsClient-2.0, jaxb-2.2, json-1.0, jpaContainer-2.1, adminCenter-1.0, cdi-1.2, distributedMap-1.0, jpa-2.1].
[AUDIT ] CWWKF0011I: The server defaultServer is ready to run a smarter planet.
[EL Info]: server: 2017-10-19 10:23:13.215--ServerSession(1864654006)--Detected server platform: org.eclipse.persistence.platform.server.was.WebSphere_Liberty_Platform.
S
Exception :
[err] javax.persistence.TransactionRequiredException:
Exception Description: No externally managed transaction is currently active for this thread
[err] at org.eclipse.persistence.internal.jpa.transaction.JTATransactionWrapper.throwCheckTransactionFailedException(JTATransactionWrapper.java:94)
[err] at org.eclipse.persistence.internal.jpa.transaction.JTATransactionWrapper.checkForTransaction(JTATransactionWrapper.java:54)
[err] at org.eclipse.persistence.internal.jpa.EntityManagerImpl.checkForTransaction(EntityManagerImpl.java:2054)
[err] at org.eclipse.persistence.internal.jpa.QueryImpl.executeUpdate(QueryImpl.java:291)
[err] at com.bcbsnc.providers.dao.JPADao.purgeBxTables(JPADao.java:49)
The executeUpdate() method requires for the EntityManager to be enlisted with a transaction - a global transaction in this case since you have defined a JTA-type persistence unit. You have chosen to use JPA's JSE bootstrapping approach (using Persistence.createEntityManagerFactory() instead of injection via #PersistenceContext or #PersistenceUnit) -- while I don't endorse using the JSE bootstrapping method in an EE application, it's not dis-allowed by the spec.
However, I believe the problem you are hitting is the fact that what you have effectively here is an application-managed persistence context, and thus your application is responsible for its enlistment with the global transaction (which would have been begun automatically by the EJB container when purgeBxTables() was called, as I do not see any annotations declaring it as a bean-managed-transaction session bean) which requires calling EntityMangager.joinTransaction().
An application-managed EntityManager will only join the global transaction automatically when the EntityManager is first created. Which is not the case for your application since the EntityManager is created when the bean class is constructed. Otherwise, the joinTransaction() method invocation is required in order for an EntityManager to join a new transaction.
Your application will need to call em.joinTransaction() before you call executeUpdate().
Using a container managed persistence context (using #PersistenceContext to inject an EntityManager) would have had the EntityManager automatically join the global transaction (unless you override the default Transaction SynchronizationType to UNSYNCHRONIZED.)
GlassFish 4 (actually its JPA implementation, i.e. EclipseLink) fails to lazy load a #ManyToOne JPA relation from our Java EE 7 application. Default/eager loading is ok, but not lazy loading.
The relation in the 'Student' entity is:
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "addr_id")
private Address address;
The (simplified) persistence.xml looks like:
<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="foo-PU" transaction-type="JTA">
<jta-data-source>jdbc/foo-DS</jta-data-source>
<class>foo.domain.Student</class>
<class>foo.domain.Address</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-database" value="PostgreSQL"/>
<property name="eclipselink.logging.level" value="FINE"/>
</properties>
</persistence-unit>
</persistence>
The application uses several API: PrimeFaces, JSF 2.2, CDI 1.1, JPA 2.1.
Also note that the EntityManager are not obtained by injection into session EJB, but manually created using Persistence.createEntityManagerFactory(...) then emf.createEntityManager(...).
The error message is:
WARNING: Reverting the lazy setting on the OneToOne or ManyToOne attribute [address] for the entity class [class foo.domain.Student] since weaving was not enabled or did not occur.
My understanding is that, for some reason, the dynamic weaving of entities is not enabled. For a Java EE application it should be, as suggested by http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Performance/Weaving.
For the record, if we try to force the weaving using this:
<property name="eclipselink.weaving" value="true"/>
in the persistence.xml, then we get another error message:
SEVERE: Error Rendering View[/student/studentList.xhtml]
javax.el.ELException: /student/studentList.xhtml #24,81 value="#{studentController.selectedCode}": Exception [EclipseLink-30005] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.PersistenceUnitLoadingException
Exception Description: An exception was thrown while searching for persistence archives with ClassLoader: WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28022] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Value [true] for the property [eclipselink.weaving] is incorrect when global instrumentation is null, value should either be null, false, or static.
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
at javax.faces.component.UIOutput.getValue(UIOutput.java:174)
at javax.faces.component.UIInput.getValue(UIInput.java:291)
at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:205)
(...)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
Any idea how to fix this lazy-loading issue? Why is the dynamic weaving not enabled by default ?
Thanks.
If you set eclipselink.weaving to true it means that you want to weave an entity classes dynamically. To make this work you need to run a jvm with a proper javaagent. First download an agent
wget -O /tmp/eclipselink.jar \
https://repo1.maven.org/maven2/org/eclipse/persistence/eclipselink/2.7.7/eclipselink-2.7.7.jar
and then run your app using following snippet
java -javaagent:/tmp/eclipselink.jar ....
But if you set eclipselink.weaving to static then you inform jpa that you want to weave the entity classes statically. Of course you have to trigger the waving by your own for example using this maven plugin https://github.com/craigday/eclipselink-staticweave-maven-plugin
I want to use proxy authentication to an Oracle Express database in a simple web app with java EE 6 on Glassfish. Eclipselink 2.3.0 doc here says:
If a JEE and JTA managed EntityManager is used, specifying a proxy user/password can be more difficult, as the EntityManager and JDBC connection is not under the applications control. The persistence unit properties can still be specified on the EntityManager. As long as this is done before the EntityManager has established a database connection, this will still work.
My code is as below, but I guess the database connection is already established when the #Postconstruct init() method is called, since the last property is not changed from default true to false.
Also, I get ORA-00942: table or view does not exist from the save() method. The user pool in the jdbc connection pool defined in glassfish-resources.xml has not acces to the tables, as has proxy user user_a.
#Stateless
public class Boundary {
#PersistenceContext EntityManager em;
#PostConstruct
private void init() {
em.setProperty("eclipselink.oracle.proxy-type", OracleConnection.PROXYTYPE_USER_NAME);
em.setProperty(OracleConnection.PROXY_USER_NAME, "pool[user_a]");
em.setProperty(OracleConnection.PROXY_USER_PASSWORD, "pool");
em.setProperty(OracleConnection.PROXY_ROLES, "pool_user");
em.setProperty("eclipselink.jdbc.exclusive-connection.mode", "Always");
em.setProperty("eclipselink.jdbc.exclusive-connection.is-lazy", "false");
}
public void save() {
em.merge(new AnEntity());
}
}
I have not much experience here, but it would be really useful if proxy authentication could be made that simple, so I spent some time trying.
In a JavaEE managed context, is it possible to set properties on an EntityManager before it gets connected?
My persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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="ProxyUserPU" transaction-type="JTA">
<jta-data-source>SecondTry</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<property name="eclipselink.target-database" value="Oracle"/>
<property name="eclipselink.jdbc.exclusive-connection.is-lazy" value="true"/>
</properties>
</persistence-unit>
</persistence>
I don't think PostConstruct is the correct place for this.
A new EntityManager is bound to the persistence context on every transaction boundary, so you need to set these property at the start of every transactional SessionBean method. You could probably also use SessionEvents in EclipseLink to configure the properties.
If you properties are fixed, you could also put them in your persistence.xml.
See,
http://wiki.eclipse.org/EclipseLink/Examples/JPA/Auditing#Use_Oracle_proxy_authentication_to_allow_a_shared_connection_pool_and_a_user_context
I need to detach some entity objects from the database to make them unmanaged. I use EclipseLink persistence provider, which method EntityManager.detach() is exactly one I need. The problem is that JBoss throws at runtime following exception (when execution passes to detach()):
javax.ejb.EJBTransactionRolledbackException: Unexpected Error
java.lang.NoSuchMethodError: javax.persistence.EntityManager.detach(Ljava/lang/Object;)V
Other methods like persist, merge, find work fine. I tried Hibernate and know that its Session provides a special method evict(), which detaches entity, but EclipseLink has no such method.
Example of using detach():
#PersistenceContext(unitName="Course7-ejbPU")
protected EntityManager manager;
(...)
Query query;
List<Message> resultList;
query = manager.createNamedQuery("Message.getUserInputMessageList");
query.setParameter("login", login);
query.setMaxResults(5);
resultList = query.getResultList();
for (Message message : resultList)
if (message.getContent().length() > 50)
{
manager.detach(message);
message.setContent(message.getContent().substring(0, 50) + "...");
}
Persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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="Course7-ejbPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:/Course7ds</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-server" value="JBoss"/>
</properties>
</persistence-unit>
</persistence>
Library with provider data is included into ear archive.
EclipseLink version is 2.2.0 (tested with 2.3.2 - no difference), JBoss server version 5.1.0. Any suggestions will be appreciated.
This exception shows that you're not using JPA2, but JPA1. You should probably use a more recent version of JBoss, that ships with JPA2.
You compiled your code with JPA 2.0 classes, but you run it with JPA 1.0. This is why the JVM doesn't find the detach method.
In reaction to your comment: no, the detach method is not useless for JPA 1.0 user: it's just it has not been created yet. You can however erase all the L1 cache by calling clean() on the entitymanager, which will detach all your managed entities...
You can still be able to detach an entity by using persistence provider specific code.
It is not because the entity manager does not provide a function yet, that the jpa providers hasn't implemented it yet.
If you can couple a little bit your code to your jpa provider:
You can call the em.getDelegate() method that will return you an EclipseLink entity manager implementation (check in debug the returned value and cast it) which may perhaps give you the possibility to detach your entity.
The method may not be named detach() -> for Hibernate it's evict().
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>