EntityManager JNDI Lookup - java

What is the correct JNDI string to look up this persistence unit JPA-DB that is shown on JBoss 6 Startup here:
10:26:09,847 INFO [PersistenceUnitDeployment] Starting persistence unit persistence.unit:unitName=tpar.ear/tpar-jboss-ejb3.jar#JPA-DB
10:26:09,847 INFO [Ejb3Configuration] Processing PersistenceUnitInfo [
name: JPA-DB
...]
10:26:09,847 WARN [Ejb3Configuration] Persistence provider caller does not implement the EJB3 spec correctly.PersistenceUnitInfo.getNewTempClassLoader() is null.
...
...
10:26:10,950 INFO [NamingHelper] JNDI InitialContext properties:{java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory, java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces}
10:26:10,950 INFO [NamingHelper] Creating subcontext: persistence.unit:unitName=tpar.ear
10:26:10,950 INFO [SessionFactoryObjectFactory] Bound factory to JNDI name: persistence.unit:unitName=tpar.ear/tpar-jboss-ejb3.jar#JPA-DB
10:26:10,950 INFO [NamingHelper] JNDI InitialContext properties:{java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory, java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces}
I have tried the following and various others that I don't remember now and they all throw the NameNotFoundException:
entityManager = (EntityManager) jndi.lookup("java:/EntityManagers/JPA-DB");
entityManager = (EntityManager) jndi.lookup("java:comp/EntityManagers/JPA-DB");
entityManager = (EntityManager) jndi.lookup("java:comp/env/JPA-DB");
entityManager = (EntityManager) jndi.lookup("JPA-DB");

I was able to find the name by looking at the JNDI Tree view:
Go to http://localhost:8080/jmx-console
Search for JNDIView and click the link service=JNDIView
Invoke button for the list() method.
Search for the persistence name on the result tree view.
It looks like this:
Global JNDI Namespace
+- persistence.unit:unitName=tpar.ear (class: org.jnp.interfaces.NamingContext)
| +- tpar-jboss-ejb3.jar#JPADB (class: org.hibernate.impl.SessionFactoryImpl)
Though, the object is actually a SessionFactoryImpl and not an EntityManager.
Additionally, the jndi lookup string generated by JBoss is hideous:
jndi.lookup("persistence.unit:unitName=tpar.ear/tpar-jboss-ejb3.jar#JPADB");
By adding the following property to the persistence.xml, I can look up using a shorter name while getting the object as an EntityManager at the same time:
<property name="jboss.entity.manager.jndi.name" value="tpar/entity-manager"/>
Note that using the long JNDI name still returns SessionFactoryImpl object in case anyone wants a SessionFactory.

Related

Can't config Java Spring Boot data session Mongodb

I've been using this guide to set up spring session data with mongodb
https://docs.spring.io/spring-session-data-mongodb/docs/2.1.1.RELEASE/reference/htmlsingle/#introduction
However I am having problems with configuration. I'm using Mongodb with Spring boot and I'm trying to config my session time and session name for Spring boot web application, but it keeps defaulting to 30 minutes and the collection name in mongodb is still 'sessions'
These are what I have tried:
Added these to application.properties:
server.session.timeout=1
spring.session.mongodb.collection-name=TestSESSIONS
and this
server.servlet.session.timeout=60s
spring.session.mongodb.collection-name=TestSESSIONS
none of those config work
I've looked over this URL for spring common application properties for mongodb but none of it help to config the session time and collection name for mongodb.
After doing hours of research it seems like spring boot uses some kind of autoconfig with this "org.springframework.boot.autoconfigure"
so then I added this in my application.properties
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration
to disable the autoconfigure.
but now it just give me this error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method mongoSessionRepository in org.springframework.session.data.mongo.config.annotation.web.http.MongoHttpSessionConfiguration required a bean of type 'org.springframework.data.mongodb.core.MongoOperations' that could not be found.
The following candidates were found but could not be injected:
- Bean method 'mongoTemplate' in 'MongoDataAutoConfiguration' not loaded because AnyNestedCondition 0 matched 2 did not; NestedCondition on MongoDataAutoConfiguration.AnyMongoClientAvailable.FallbackClientAvailable #ConditionalOnBean (types: com.mongodb.client.MongoClient; SearchStrategy: all) did not find any beans of type com.mongodb.client.MongoClient; NestedCondition on MongoDataAutoConfiguration.AnyMongoClientAvailable.PreferredClientAvailable #ConditionalOnBean (types: com.mongodb.MongoClient; SearchStrategy: all) did not find any beans of type com.mongodb.MongoClient
Action:
Consider revisiting the entries above or defining a bean of type 'org.springframework.data.mongodb.core.MongoOperations' in your configuration.
this is the #bean from the spring.io guide 'mongoSessionConverter' from above link
this is the java file MongoHttpSessionConfiguration from spring that that's autoconfig by spring; I have tried extending "MongoHttpSessionConfiguration" and overriding the setter methods my self. Such as the "setMaxInactiveIntervalInSeconds" for sessionTime and
"setCollectionName" for mongododb database collection name.
but I've have this error:
Description:
The bean 'mongoSessionRepository', defined in class path resource [com/khatpass/app/config/SessionListenerConfig.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/session/data/mongo/config/annotation/web/http/MongoHttpSessionConfiguration.class] and overriding is disabled.
I am stuck on trying to configure spring boot session with Mongodb. The session always defaulting to 30 minutes and the collection name is always 'sessions' in mongodb collections. Not sure how to change that serverSelectionTimeout='30000 ms' and mongodb collections name "sessions" I don't know what to do, need help.
2019-02-24 13:39:54.501 INFO 36113 --- [ main] org.mongodb.driver.cluster : Cluster created with settings {hosts=[localhost:27017], mode=MULTIPLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
After doing so much research and then finally, going through the source code, I found the solution:
#EnableMongoHttpSession(maxInactiveIntervalInSeconds = 24 * 60 * 60)
public class SessionConfiguration {}
To override the default collection name, there is another annotation attribute collectionName.
This is working for Spring Boot 2.1.1
After looking over the class MongoOperationsSessionRepository from org.springframework.session.data.mongo it seems like it can't be config through application.properties because the class is using static final values
public static final int DEFAULT_INACTIVE_INTERVAL = 1800;
and
public static final String DEFAULT_COLLECTION_NAME = "sessions";
only way to change the value is intercept the object before it gets saved. No getters or setters for those fields, it can't be change in an easy way, what a joke!

How to have more than one persistence units in an JPA 2 application?

My system:
Eclipse Oxygen/JPA 2/JSF 2.2/Hibernate 4/JBoss AS 7
My condition:
I have an application with two persistence units (PU) declared in persistence.xml.
My JBoss error:
Caused by: java.lang.IllegalArgumentException: JBAS011470: Persistence unitName was not specified and there are 2 persistence unit definitions in application deployment "test.war". Either change the application to have only one persistence unit definition or specify the unitName for each reference to a persistence unit.
at org.jboss.as.jpa.container.PersistenceUnitSearch.resolvePersistenceUnitSupplier(PersistenceUnitSearch.java:69)
at org.jboss.as.jpa.processor.JPAAnnotationParseProcessor.getPersistenceUnit(JPAAnnotationParseProcessor.java:284)
at org.jboss.as.jpa.processor.JPAAnnotationParseProcessor.getBindingSource(JPAAnnotationParseProcessor.java:220)
at org.jboss.as.jpa.processor.JPAAnnotationParseProcessor.processField(JPAAnnotationParseProcessor.java:151)
at org.jboss.as.jpa.processor.JPAAnnotationParseProcessor.processPersistenceAnnotations(JPAAnnotationParseProcessor.java:118)
at org.jboss.as.jpa.processor.JPAAnnotationParseProcessor.deploy(JPAAnnotationParseProcessor.java:90)
at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:113) [jboss-as-server-7.1.0.Final.jar:7.1.0.Final]
... 5 more
My problem:
I use a framework that hides all the details on the EntityManager lifecycle. This framework gives me an ancestor class and I build all my code in a subclass, not caring about managing the EntityManager.
This ancestor class does not inject ou annotate the EntityManager, it is created by code when needed for the first time, but the exception above is thrown by JBoss during the application start when I have more than one PU.
I wrote a code in the ancestor to accept the #PersistenceUnit annotation in my subclass and to use the name set in the annotation when creating the EntityManagerFactory. When no annotation is used, the code finds out the first PU name and used it. So, the first PU existing in persistence.xml is understood as a default PU name.
However, even not injecting any EntityManagers, I still have the above exception.
What is missing in my solution?
If you have more than one persistence unit and use #PersistenceContext/#PersistenceUnit annotations, you must specify your unit name for the annotation to be unambiguous.
So instead of:
#PersistenceContext
private EntityManager manager;
you must use:
#PersistenceContext(unitName = "<unit name in persistence.xml>")
private EntityManager manager;
And instead of:
#PersistenceUnit
private EntityManagerFactory managerFactory;
you must use:
#PersistenceUnit(unitName = "<unit name in persistence.xml>")
private EntityManagerFactory managerFactory;
What the error message tells you is that the deployer has found at least one occurrence of #PersistenceContext/#PersistenceUnit without specifying a persistence unit name. That is ambiguous.

EJB with CMT when migrate from JBoss 7 to WildFly 9

I'm migrating my application from JBoss 7 to WildFly (v9.0.1) and it is not deployed because of bean transaction management error.
Caused by: javax.naming.NamingException: WFLYNAM0062: Failed to lookup env/com.component.eventmgt.EventServiceImpl/transaction [Root exception is java.lang.RuntimeException: WFLYNAM0059: Resource lookup for injection failed: java:jboss/UserTransaction]
at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:157)
at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:83)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:207)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:193)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:189)
at org.jboss.as.naming.deployment.ContextNames$BindInfo$1$1.getReference(ContextNames.java:316)
... 90 more
Caused by: java.lang.RuntimeException: WFLYNAM0059: Resource lookup for injection failed: java:jboss/UserTransaction
at org.jboss.as.naming.deployment.ContextNames$BindInfo$1$1.getReference(ContextNames.java:319)
at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:143)
... 95 more
Caused by: javax.naming.NameNotFoundException: UserTransaction [Root exception is java.lang.IllegalStateException: WFLYEJB0137: Only session and message-driven beans with bean-managed transaction demarcation are allowed to access UserTransaction]
at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:153)
at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:83)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:207)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:193)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:189)
at org.jboss.as.naming.deployment.ContextNames$BindInfo$1$1.getReference(ContextNames.java:316)
... 96 more
Here is the EventServiceImpl class.
#Stateless
#Remote(EventService.class)
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class EventServiceImpl implements EventService {
/**
* Logger
*/
private static Logger log = LoggerFactory.getLogger(EventService.class);
private EventTableDAO eventDao;
#PersistenceContext(unitName = "SOMF-GT")
private EntityManager entityManager;
#Resource
private UserTransaction transaction;
public List<Map> loadEvents() throws EventsException {
Configuration configurationEntry = new Configuration();
try {
Map configuration = configurationService.getConfiguration();
if (configuration != null) {
eventDao = new EventTableDAO(Event.class, entityManager, transaction);
List<Map> eventsMapList = new ArrayList();
}
}
I know that if i changed the transaction management to BMT with #TransactionManagement(TransactionManagementType.BEAN) but then the following error emerge
WFLYJPA0060: Transaction is required to perform this operation (either use a transaction or extended persistence context)
I want to know why we have to change this in the first place ?
Any information, please !
These changes rolled out in Wildfly 8 and were (as noted below) based on standardization of the global JNDI namespace in EJB 3.1.
From the Wildfly 8 Developer Guide:
EJB 3.1 introduced a standardized global JNDI namespace and a series of related namespaces that map to the various scopes of a Java EE application. The three JNDI namespaces used for portable JNDI lookups are java:global, java:module, and java:app. If you use JNDI lookups in your application, you will need to change them to follow the new standardized JNDI namespace convention.
To conform to the new portable JNDI namespace rules, you will need to review the JNDI namespace rules and modify the application code to follow these rules.
The guide further notes:
WildFly 8 has tightened up on JNDI namespace names to provide predictable and consistent rules for every name bound in the application server and to prevent future compatibility issues. This means you might run into issues with the current namespaces in your application if they don't follow the new rules.
Here's a snippet from the table showing Examples of JNDI mappings in previous releases and how they might look now specific to the UserTransaction:
Previous Namespace New Namespaces
------------------ --------------
java:comp/UserTransaction java:comp/UserTransaction (This will not be accessible for non EE threads, e.g. Threads your application directly creates)
java:comp/UserTransaction java:jboss/UserTransaction (Globally accessible, use this if java:comp/UserTransaction is not available)
Edit re: WFLYEJB0137:
This is theory-craft and may be worthless - let me know and I'll delete it. Java EE 6 Tutorial - Container-Managed Transactions says:
Enterprise beans that use container-managed transaction demarcation also must not use the javax.transaction.UserTransaction interface.
Further:
(Transaction) Required Attribute
If the client is running within a transaction and invokes the enterprise bean’s method, the method executes within the client’s transaction. If the client is not associated with a transaction, the container starts a new transaction before running the method.
The Required attribute is the implicit transaction attribute for all enterprise bean methods running with container-managed transaction demarcation. You typically do not set the Required attribute unless you need to override another transaction attribute. Because transaction attributes are declarative, you can easily change them later.
The exception message pretty much says it all:
WFLYEJB0137: Only session and message-driven beans with bean-managed transaction demarcation are allowed to access UserTransaction
Your EJB is using container managed transaction (CMT) demarcation which does not inter-operate with bean managed transaction (BMT) demarcation wherein UserTransaction lies.
Regarding a switch to BMT and
WFLYJPA0060: Transaction is required to perform this operation (either use a transaction or extended persistence context)
I found Transaction is required to perform this operation (either use a transaction or extended persistence context) which seems to indicate that the transaction is to be managed by you, as you noted in your comments #Marco. It appears that you have made the appropriate modification.

Spring is unable to inject an EntityManager using #PersistenceContext

I have a Java 8/spring 4.3.5.RELEASE web application tha runs on a wildfly 10 server. I use a persistence.xml file. I enabled trace logging on the jboss jpa and hibernate classes and I can see this file gets picked up and is resolved smoothly into a persistence unit:
DEBUG [] [org.hibernate.jpa.internal.util.LogHelper] PersistenceUnitInfo [
name: testcontext
persistence provider classname: org.hibernate.jpa.HibernatePersistenceProvider
classloader: ModuleClassLoader for Module "deployment.BasicWebapp.war:main" from Service Module Loader
excludeUnlistedClasses: false
JTA datasource: org.jboss.as.connector.subsystems.datasources.WildFlyDataSource#fb80232
Non JTA datasource: null
Transaction type: JTA
PU root URL: vfs:/C:/Users/Me/Wildfly 10.0.0/standalone/deployments/BasicWebapp.war/WEB-INF/classes/
Shared Cache Mode: UNSPECIFIED
Validation Mode: AUTO
Jar files URLs []
Managed classes names [
com.company.project.data.User]
Mapping files names []
Properties [
jboss.entity.manager.jndi.name: persistence/testcontext]
I now want a dao class to have an entity manager injected by spring:
UserDao.class
#Repository
public class UserDao
{
#PersistenceContext(unitName = "testcontext")
private EntityManager entityManager;
}
I have component scanning and annotation config so both the #Repository and the #PersistenceContext annotation gets processed upon starting my application:
spring-servlet.xml
<context:component-scan base-package="com.company.project" />
<context:annotation-config/>
<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/testcontext"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"/>
<tx:annotation-driven/>
The injection fails though, in two possible ways:
If I use #PersistenceContext(unitName = "testcontext"), the error is:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'testcontext' available
If I use #PersistenceContext, the error is:
Caused by: java.lang.NullPointerException
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:580)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:546)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:707)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:680)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:354)
... 44 more
So I'm missing something in this configuration to tell the part of Spring that processes the #PersistenceContext annotation to look at either the entityManagerFactory bean that I declared in the spring-servlet.xml or just use the container's persistence unit directly. What do I need to add to achieve that?
I'm also a bit sketchy on the transactionmanager part. Does wildfly provide the transactionmanager or not? If it does, do I need to create a bean for it in Spring (will it pick up the one created by jboss or make its own one?)
I think you should double check you configuration setup against Spring official docs : https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#orm-jpa-setup-jndi .No, the transaction manager is provided by Spring. More info on this: https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#transaction-strategies

EntityManager obtained from JNDI lookup is already closed

For (Glassfish v2.1), two RuntimeExceptions from two separate requests from a session bean:
"org.hibernate.SessionException: Session is closed!"
org.hibernate.SessionException: Session is closed!
at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:72)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1138)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:67)
[wrapped] javax.persistence.PersistenceException: org.hibernate.SessionException: Session is closed!
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:614)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:76)
"java.lang.IllegalStateException: EntityManager is closed"
java.lang.IllegalStateException: EntityManager is closed
at org.hibernate.ejb.EntityManagerImpl.close(EntityManagerImpl.java:97)
at com.sun.enterprise.util.QueryWrapper.clearDelegates(QueryWrapper.java:460)
at com.sun.enterprise.util.QueryWrapper.getResultList(QueryWrapper.java:198)
Both of these EntityManagers were obtained via JNDI lookup (java:comp:/env/TargetSitePersistenceContext)
Using JTA (transaction-type attribute is not defined in persistence.xml).
& SQL Server 2008 w/ sqljdbc4.jar
The code just does the ff:
query = entityManager.createQuery();
query.getResultList();
And that's it. If I'm not mistaken, I believe the app container will handle open/commit/rollback/close, so we shouldn't have any entityManager.close().
What might have caused those two runtime exceptions?
When does GF actually open/close an EntityManager?
Is there any difference between:
an EntityManager obtained via JNDI lookup
via #PersistenceContext Injection? (So far not issues with this style)
All things being equal, a #PersistenceContext injection and a JNDI lookup should return the same EntityManager. So it might be a bug of GlassFish and you might want to reach for them. But make sure to give all the context like type of session bean used for injection, transaction or not etc etc.
Mark your bean with annotation #TransactionAttribute
#Stateless
#TransactionAttribute(TransactionAttributeType.MANDATORY)
public class Repo implements IRepo
{
container managed transaction is regulated by this parameter

Categories