Is this code copmliant to Java EE spec and can be used?
#Stateless
public class SomeBean {
#Inject
protected TransactedRunner txRunner;
public void someFunc() {
txRuner.run(new Runnable(){
Connection c = ds.getConnection();
//do jdbc stuff or jpa stuff
//close everything etc.
});
}
}
#Stateless
public class TransactedRunner {
#TransactionAttribute(REQUIRES_NEW)
public void run(Runnable r) {
r.run();
}
}
In this case a new transaction should be started and every thing that will be done in runnable will be transacted. Is that right? Or there is some trick in which I should suffer from EE?
This should work as intended. But be aware, that multiple calls of txRunner.run during one service call might lead to inconsistent data if anything happens between or during those calls, like connection-timeout, transaction-timeout, or the node dies or something. And the calling transaction (if there is any) might not see the changes done during the call until it itself has been committed.
There is an annotation in JavaEE6 called #Asynchronous which is specifically for this purpose. Here is the official tutorial: http://docs.oracle.com/javaee/6/tutorial/doc/gkkqg.html
#Stateless
public class SomeBean {
#Inject
private SomeBean self;
public void someFunc() {
self.doSomething();
}
#TransactionAttribute(REQUIRES_NEW)
#Asynchronous
private void doSomething() {
Connection c = ds.getConnection();
//do jdbc stuff or jpa stuff
//close everything etc.
}
}
Also it's not allowed to create or manage Threads within a EJB Container. Check out: http://www.oracle.com/technetwork/java/restrictions-142267.html#threads
Why is thread creation and management disallowed?
The EJB specification assigns to the EJB container the responsibility for managing threads. Allowing enterprise bean instances to create and manage threads would interfere with the container's ability to control its components' lifecycle. Thread management is not a business function, it is an implementation detail, and is typically complicated and platform-specific. Letting the container manage threads relieves the enterprise bean developer of dealing with threading issues. Multithreaded applications are still possible, but control of multithreading is located in the container, not in the enterprise bean.
Method "run" will be executed in transaction, that's true. But it has nothing in common with threading or using executor. In your example, the calling thread will execute your "run" method. Runnable interface itself won't create a separate thread for you.
If you need this call to be executed by separate thread, you can use asynchronous calls, or, starting from EE7, a ManagedExecutorService is available:
http://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/ManagedExecutorService.html
Related
Here is my problem.
I have a class implements Runnable, and it is a daemon thread, which will be permanently alive during the application lifecycle.
Now I want to perform a function just like AOP enhancement to enhance this Runnable class.
It was quite easy to have that pointcut if the class is annotated with #Service or #Component. But now it is a class implememts the Runnable interface so I have not yet find any possible ways to do so without any intrusion to the original code.
Here below is my testing code:
this is the parent interface of my daemon thread
public interface MessageRunnable extends Runnable {
void doConsume();
}
one of the working thread:
#Slf4j
public class MyDaemonThread implements MessageRunnable{
#Override
public void run() {
log.info("now in run function,ready to call doConsume...");
while(true){
log.info("I m still alive...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
doConsume();
}
}
#Override
public void doConsume() {
log.info("doConsume was called...");
}
}
And here is the simple test:
#Component
public class TestComponent {
private MyDaemonThread testThread;
#PostConstruct
public void init(){
if(testThread==null){
testThread=new MyDaemonThread();
new Thread(testThread).start();
}
}
}
After running the application.
I can see the log is printing well, but now if I want to add a function to print now I'm in the aspect method before the doConsume function was invoked, I don't have any idea to do so without any intrude to my source code, it is acceptable to add codes ,but no modifications were allowed at all.
I wonder if there is any possible ways to let spring handle this daemon thread, then it is easy to do an aspect point cut. Otherwise, I have to change the code to add a proxy method and an interceptor do achieve the goal....
First of all , MyDaemonThread instance is not a spring container managed bean. The code uses new keyword to create the instance. Spring AOP can only advise a spring bean.
Even if the MyDaemonThread is made a spring bean , it is not possible to advise doConsume() using Spring AOP with the current code ( OP mentions no modifications are allowed ).
From the reference documentation
Due to the proxy-based nature of Spring’s AOP framework, calls within
the target object are, by definition, not intercepted.
Using a post construct approach when we want to conditionally initialise some of the bean's fields, do we need to care about volatility of the field, since it is a multithread environment?
Say, we have something like this:
#ApplicationScoped
public class FooService {
private final ConfigurationService configurationService;
private FooBean fooBean;
#Inject
FooService(ConfigurationService configurationService) {
this.configurationService = configurationService;
}
void init(#Observes #Initialized(ApplicationScoped.class) Object ignored) {
if (configurationService.isFooBeanInitialisationEnabled()) {
fooBean = initialiseFooBean(configurationService); // some initialisation
}
}
void cleanup(#Observes #Destroyed(ApplicationScoped.class) Object ignored) {
if (fooBean != null) {
fooBean.cleanup();
}
}
}
So should the fooBean be wrapped into, let's say, the AtomicReference or be a volatile or it would be a redundant extra protection?
P.S. In this particular case it can be reformulated as: are post construct and post destroy events performed by the same thread or not? However I would like to have an answer for a more general case.
I would say it depends which thread is actually initiating and destroying the contexts.
If you use regular events, they are synchronous (asynchronous events have been added in CDI 2.0 with ObservesAsync, see
Java EE 8: Sending asynchronous CDI 2.0 events with ManagedExecutorService ) so they are called in the same thread as the caller.
In general, I don't think the same thread is used (in application servers or standalone applications) so I would recommend using volatile to ensure the right value is seen (basically the value constructed seen on destroy thread). However, it is not a use case happening so much to initiate and destroy your application in a concurrent way...
FooService is a singleton which is shared between all managed beans in the application.
Annotation Type ApplicationScoped
private FooBean fooBean is a state of the singleton object.
By default, CDI does not manage concurrency so it is the responsibility of a developer.
In this particular case it can be reformulated as: are post construct and post destroy events performed by the same thread or not?
CDI specification does not restrict containers to use the same thread for initialization and destruction of the application context. This behavior is implementation specific. In general case those threads will be different because initialization happens on the thread handling the first request to the application but destruction happens on the thread handling request from management console.
You may delegate concurrency management to EJB container - if your runtime environment includes one.
Neither volatile nor AtomicReference are needed in this case!
Following definition will do the job:
#javax.ejb.Startup // initialize on application start
#javax.ejb.Singleton // EJB Singleton
public class FooService {
private final ConfigurationService configurationService;
private FooBean fooBean;
#javax.inject.Inject
FooService(ConfigurationService configurationService) {
this.configurationService = configurationService;
}
#javax.annotation.PostConstruct
void init() {
if (configurationService.isFooBeanInitialisationEnabled()) {
fooBean = initialiseFooBean(configurationService); // some initialisation
}
}
#javax.annotation.PreDestroy
void cleanup() {
if (fooBean != null) {
fooBean.cleanup();
}
}
}
According to the specification:
An event with qualifier #Initialized(ApplicationScoped.class) is synchronously fired when the application context is initialized.
An event with qualifier #BeforeDestroyed(ApplicationScoped.class) is synchronously fired when the application context is about to be destroyed, i.e. before the actual destruction.
An event with qualifier #Destroyed(ApplicationScoped.class) is synchronously fired when the application context is destroyed, i.e. after the actual destruction.
And according to this presentation Bean manager lifecycle: the lifecycle of the bean manager is synchronous between the different states of the process and the sequence is kept: "destroy not before init".
Jboss are the specification lead of CDI 2.0
I do not see any scenario that would require a volatile/protection. Even if T1 inits then T2 destroys, it will be T1 then T2, not T1 and T2 concurrently.
And even if it would be concurrently, to have an issue it would imply weird scenario, edge scenario outside the CDI runtime:
T2 calls destroy (fooBean is null and now 'cached' in a register)
Then T1 calls init: destroy before init, at this point we are in the 4th dimension of CDI),
Then T2 calls destroy (fooBean is already cached in a register so is value is null)).
Or
T2 calls a method that access fooBean (fooBean is null and now 'cached' in a register)
Then T1 calls init: T1 is initialized whereas fooBean has already been used by T2, at this point we are in the 4th dimension of CDI
Then T2 calls destroy (fooBean is already cached in a register so is value is null)).
If I have a stateful class that requires a utility-like stateless class to perform an operation on it. These stateful classes are kept in a list in a container (stateful) class. This is what I would do with plain Java:
class Container {
List<Stateful> sfList;
}
class Stateful {
List<String> list;
void someMethod() {
list.add("SF");
Stateless.foo(this);
}
class Stateless {
public static void foo(Stateful sf) {
sf.getList().add("SL");
}
}
and inside main this is the procedure:
Stateful sf = new Stateful();
sfList.add(sf);
sf.someMethod();
Now with JavaEE CDI I would do:
class StatefulBean {
List<String> list;
#Inject
StatelessBean slsb;
void someMethod() {
list.add("SF");
slsb.add(this);
}
#Stateless
class StatelessBean {
public void add(StatefulBean sfsb) {
sfsb.add("SL");
}
}
In this case all StatefulBean could access a shared pool of StatelessBean with no concurrency issues and it will scale properly with requests.
However, since Stateful is not a managed bean I can't inject into it and so I used the utility class instead. Also I'm creating Stateful with a constructor so I can't inject into it the stateless bean (I will get a NPE using it).
My questions are:
Are there concurrency and scalabilty differences between the stateless injection approach (provided it would work) and the utility class approach?
How can I make the EE injection approach work?
Are there concurrency and scalabilty differences between the stateless injection approach (provided it would work) and the utility class approach?
Yes there are, primarily around the loss of management. The way you're instantiating Stateful on every invocation of the method, there's no pooling involved. This is going to lead to you creating more instances than you probably need.
Another loss is on the scalability side. Where the container will manage the passivation and activation of your stateful bean in a distributed environment, the manual approach will see to it that you manage your own activation and passivation.
Since Stateful is not a managed bean..
Incorrect. According to the CDI Spec, any java class that meets the listed criteria (in your case, a default no-arg constructor) is a managed bean. That means that you could #Inject StatelessBean into Stateless and the container would oblige. To allow this level of management, you'll need to set bean-discovery-mode=all in your beans.xml.
Even with the (apparently needless) circular reference, normal Java concurrency rules apply: as long as the state that you're manipulating is not static or in a static class, you're threadsafe. Each threaded call to that static method still operates on a separate stack, so no problems there.
How can I make the EE injection approach work?
If you need on-demand instantiation of Stateless(or any other bean really), use the CDI Instance to programmatically obtain a managed instance of any class you want. You can now add something like this to Container:
#Inject #Dependent Instance<Stateful> stateful;
#PostConstruct
public void createStateless(){
//instantiate sfList;
sfList.add(stateful.get()); //execute as many times as you need
}
Is it allowed to use libraries inside an EJB which are spawning and manage threads?
I wrote a JavaSE library with a class like this:
public class LibraryClass {
public void longRunningMethod() {
ExecutorService service = Executors.newFixedThreadPool(10);
//schedule tasks
service.shutdown();
try {
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Example EJB:
#Stateless
class Bean {
public void beanMethod() {
LibraryClass libraryClass = new LibraryClass();
libraryClass.longRunningMethod();
}
}
Would it be ok to use something like this inside an EJB?
The specification states that "The enterprise bean must not attempt to manage threads", would this still apply if the threads are managed outside of the EJB, maybe even out of control of the developer (for example when using 3rd party libraries)?
Hi in general the suggestion is true. It is a bad practice, since you are already running on a 'contained' environment that already does the heavy lifting of thread handling /hread pooling (allocation) for you. In case that you really want to span threads you should, make sure that the container is aware of them or provide him the constructs so that it can handle and monitor it. This is materialized with the use of the Executor Service in Java.See here and here
I'm developing a JEE application where each request done to "facade" beans should run a single transaction.
Basicly, in each method, I could do it like this:
#Override
public void updateSalaries(float factor)
{
initializeTransaction();
// Actual business code...
commitTransaction();
}
Where ùpdateSalaries()is a method invoked by the client, and whereinitializeTransaction()andcommitTransaction()` respectively take care of getting/starting/committing/rolling back (if necessary) the transaction.
Unfortunately, the transaction management should be more transparent: something developers should not care about when writing business methods.
Therefore, some way to "decorate" these business methods would be nice, but I can't think of a possible way to do that.
Another possible solution I thought of would be to handle it in a central DataAccessBean class, where I would start the transaction on #PostConstruct and commit it on #PreDestroy:
#Stateless
public class DataAccessBean implements IDataAccessBean
{
#PostConstruct
public void initializeTransaction() { /* ... */ }
#PreDestroy
public void endTransaction() { /* ... */ }
#Override
public <T implements Serializable> T getObjectById(
Class<T> objectType, Object key) { /* ... */ }
#Override
public void saveObject(Serializable object) { /* ... */ }
}
I'm not sure though, if I can rely on that mechanism. An important question would also be, what type of bean I'd need: I doubt a stateful bean would be suitable as the transaction is per-request and not per-session. Maybe a stateless bean would be a good option, but AFAIK a stateless bean might not be destroyed when a request completes (if it resides in a stateless bean pool).
Two little constraints:
The solution should not depend on a particular non-standard framework or JEE-server
The solution should be compatible with JEE 6 and JEE 7
Thanks for the suggestions.
What you need is addressed by Java Transaction API (JTA). From the JEE6 Tutorial (Part VIII - Chapter 42):
The Java Transaction API (JTA) allows applications to access transactions in amanner that is
independent of speciic implementations. JTA speciies standard Java interfaces between a
transactionmanager and the parties involved in a distributed transaction system: the
transactional application, the Java EE server, and themanager that controls access to the shared
resources afected by the transactions.
You want to use the Container-Managed Transaction. In this strategy you just need decorate the beans/methods with the appropriate transaction attribute i.e.:
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void myMethod() {
...
}
The design of your service layer must carefully address the transaction life cycle in case your have services of services (nested service calls).