I am using the java Batch (JSR-352), it is possible to work with a session bean inside it? I needed to have a Bean with #SessionScope annotation, to catch some information in it, that to differentiate the type of User that is running the batch process.
It's possivel use a Session Context CDI inside the specification ? If is possible how is the best pratice
In general, the session isn't going to propagate from the thread starting the job via JobOperator to the execution thread. I don't recall if this is under discussion in the CDI specification still or a settled matter, but for now you can't.
Related
I have a code which does context lookup to get UserTransaction JNDI as ctx.lookup("java:comp/UserTransaction").
When I run this code without using CompletableFuture, it works as expected.
When working with CompletableFuture in async thread, it gives exception saying jndi lookup failed.
I tried to check if I can get the required JNDI from global scope, but no luck.
CompletableFutures often run on the JDK's ForkJoinPool rather than application server managed threads, and so lack access to services provided by the application server. MicroProfile Context Propagation (available in Liberty) solves this problem by giving you a way to create CompletableFutures that run on the Liberty thread pool and with access to application component context.
In server.xml,
<featureManager>
<feature>mpContextPropagation-1.2</feature> <!-- 1.0 is also valid -->
<feature>jndi-1.0</feature>
<feature>jdbc-4.2</feature> <!-- or some other feature that participates in transactions -->
... other features
</featureManager>
In your application,
import org.eclipse.microprofile.context.ManagedExecutor;
import org.eclipse.microprofile.context.ThreadContext;
...
ManagedExecutor executor = ManagedExecutor.builder()
.propagate(ThreadContext.APPLICATION)
.build();
CompletableFuture<?> f = executor.supplyAsync(() -> {
UserTransaction tx = InitialContext.doLookup("java:comp/UserTransaction");
...
});
...
executor.shutdown();
If you don't want to construct a new ManagedExecutor, Liberty will also let you cast an EE Concurrency ManagedExecutorService to ManagedExecutor and use that. For example,
ManagedExecutor executor = InitialContext.doLookup("java:comp/DefaultManagedExecutor");
It should also be noted that with a ManagedExecutor, the application context is made available to dependent stages as well as the initial stage, allowing you to perform the lookup in a dependent stage such as the following if you prefer:
executor.supplyAsync(supplier).thenApplyAsync(v -> {
UserTransaction tx = InitialContext.doLookup("java:comp/UserTransaction");
...
});
The problem seems to be that the JNDI context is not propagated to the async thread, so when the CompletionStage attempts to execute the JNDI lookup, it has no context, so it doesn't know which component it is in and thus fails.
There is a very detailed explanation of context propagation and how to do it effectively in Open Liberty (which is the underlying product for WebSphere Liberty) at https://openliberty.io/docs/21.0.0.8/microprofile-context-propagation.html - I'd highly suggest reading it.
Certain Java/Jakarta/MicroProfile APIs will allow you to specify the async service (ExecutorService) to use for the async operation. If possible, you can pass it an instance of ManagedExecutorService which should propagate contexts (like JNDI, security, classloading, etc.) to the async thread. Otherwise, you may need to specify the managed executor service when constructing your CompletionStage.
I am taking the LazyInitializationException error when because in myController when I read the Lazy collections session is already closed. Is there any way to get it open as long as there is a request? As OpenSessionInView? What would be the best way?
I'm using the version of Spring Boot 1.3.0
You need use the "open session in view" to keep the session open after the end of the transaction.
see OpenSessionInViewFilter or OpenEntityManagerInViewFilter for JPA
imho it's better than extending the scope of the transaction to your controller.
If you're using a jackson/hibernate combination you can register the jackson-datatype-hibernate module, and tweak the Feature.FORCE_LAZY_LOADING property to your liking. The default is false means that only already fetched properties will be serialized. Changing to true will force initialization of the lazy properties
I got below exception when I used session.getCurrentSession().
I have mentioned
hibernate.current_session_context_class: managed
org.hibernate.HibernateException: No session currently bound to execution context
at org.hibernate.context.internal.ManagedSessionContext.currentSession(ManagedSessionContext.java:75)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
at io.dropwizard.hibernate.AbstractDAO.currentSession(AbstractDAO.java:36)
at io.dropwizard.hibernate.AbstractDAO.persist(AbstractDAO.java:149)
I use this with dropwizard. Can anyone help me to solve this?
If you are using Dropwizard Hibernate. You need to add #UnitOfWork annotation to your Resource method. More info within dropwizard manual, hibernate chapter.
Can you try with : session.openSession() - It tell hibernate to always opens a new session and you have to close once you are done with the operations. With session.getCurrentSession(), hibernate returns a session bound to a context that you don't need to close and only need to set the hibernate.current_session_context_class to thread.
You can also configure session with SpringSessionContext, if your application is Spring based.
Edit your hibernate-cfg.xml with below line:
hibernate.current_session_context_class=org.springframework.orm.hibernate3.SpringSessionContext
What above line will do?
Making session context class as "org.springframework.orm.hibernate3.SpringSessionContext
", Hibernate will assume it is executing inside of a Spring transactional context (i.e. through a Spring transactional aspect) and Spring will now manage your transaction for you. However if you call getCurrentSession() outside of such a context, Hibernate will throw an exception complaining that no Session is bound to the thread.
I have two Spring applications, applA and applB, running in Tomcat - both use jarX.jar and applicationContext-x.xml.
So there's going to be one instance of a certain bean, defined in the above context, for each application.
I'm exposing the bean and some of its methods via JMX by using annotations.
now i want to write a test client which calls method of the bean, but sometimes i want to call the methods of the bean in applA and sometimes of the bean in applB.
How do i do that?
i also have a bean called jmxServerConfiguration in each application, each using a different port though.
currently in my JMX client i'm getting the bean by using
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(applicationContextName);
theBean = beanFactory.getBean(BEAN_NAME);
but i always get the bean of applA. how do i tell it whether i want the bean of applB or applA?
Should i perhaps, (how?), use
MBeanServerConnection connection = JmxUtils.getMBeanServerConnection(url);
and specify a different port in the url, depending on the appl from which i want to get the bean?
Set the default-domain on the MBean exporter to a different value for each application and use the appropriate ObjectName to access the bean(s) over JMX.
I have a Spring 3 application using openJPA as persistence management, following section works fine in STS/Tomcat
#Transactional
createBalance(){
.....
Balance balance = new SummaryBalance();
balance.setName(name);
balance.setCurrency(currency);
balance.setClosingTimestamp(closingTime);
balance.setStatus(BalanceStatus.OPEN);
balance.persist(); // persist !!
......
balance.setCloseAmount(amount);
balance.setLastUpdateTimestamp(now);
}
However, when deploying same code in websphere 7, the closeAmount and lastUpdate does not update(both fields in DB didn't get update but from log both field can return values by their getter) then show up as null, but changes to other fields before persist() do take effect when the method finished. So I bet when the method finishing WS didn't flush the changes towards these fields.
I thought the JPA(regardless of vendor) should keep the balance entity object managed after persist() and flush the object after the method is finished with later changes. Turns out Websphere 7 doesn't make it. Even I put a merge() method
balance.setCloseAmount(amount);
balance.setLastUpdateTimestamp(now);
balance.merge();
still does not help.
Questions:
OpenJPA has already been included as dependencies in the deployment, but why still websphere need to involve with the JPA management?
How to solve the problem?
Thanks in advance.
I'm not sure that this exactly answers your question, but I think you should do some reconfiguration to use WebSphere capabilities, please check Spring 3.1 documentation
11.8.1 IBM WebSphere
On WebSphere 6.1.0.9 and above, the recommended Spring JTA transaction
manager to use is WebSphereUowTransactionManager. This special adapter
leverages IBM's UOWManager API, which is available in WebSphere
Application Server 6.0.2.19 and later and 6.1.0.9 and later. With this
adapter, Spring-driven transaction suspension (suspend/resume as
initiated by PROPAGATION_REQUIRES_NEW) is officially supported by IBM!
and
11.9.1 Use of the wrong transaction manager for a specific DataSource
Use the correct PlatformTransactionManager implementation based on
your choice of transactional technologies and requirements. Used
properly, the Spring Framework merely provides a straightforward and
portable abstraction. If you are using global transactions, you must
use the org.springframework.transaction.jta.JtaTransactionManager
class (or an application server-specific subclass of it) for all your
transactional operations. Otherwise the transaction infrastructure
attempts to perform local transactions on resources such as container
DataSource instances. Such local transactions do not make sense, and a
good application server treats them as errors.
Figure out a solution myself with guess work. Simply just place the persist() by the end of the whole method body.
#Transactional
createBalance(){
.....
Balance balance = new SummaryBalance();
balance.setName(name);
balance.setCurrency(currency);
balance.setClosingTimestamp(closingTime);
balance.setStatus(BalanceStatus.OPEN);
......
balance.setCloseAmount(amount);
balance.setLastUpdateTimestamp(now);
......
balance.persist(); // persist !!
}
That can make sure every fields are set before the method finished.
Both merge() and explicit flush() won't do the job but only with above compromise. Still not quite sure about the official work around....
I will keep this thread open for any new thinking come in :)