I want to call to a method from an EJB in the same instant in which one deploys itself, without using a servlet.
Thanks.
David.
There seems to be no life-cycle methods defined by the EJB spec for this purpose. Individual vendors may provide extensions to allow this. For example Startup Beans in WebSphere would be a place to put the invocation logic you want.
Using techniques such as a static method seem slightly dangerous in that we don't know whether all dependency injection is complete before that static method fires, and hence whether you can safely use the business methods of the EJB.
Persoanlly, if I needed to be portable I would bite the bullet and use a servlet. It costs very little.
Try doing your initialization within a static block. This will run once when the classloader loads the class.
static { System.out.println("static"); }
The PostConstruct hook is right for that.
Find more info on about PostConstruct here:
in the javadoc
lifecycle of EJBs in the JavaEE 5 tutorial
Let's finish with a quick example:
#Stateless
public class TestEJB implements MyEJBInterface{
#PostConstruct
public void doThatAfterInitialization() {
//put your code here to be executed after creation and initialization of your bean
}
}
Static initializer blocks are technically not illegal in EJB but they are used to execute code before any constructor (which might be a problem) when instantiating a class. They are typically used to initialize static fields which may be illegal in EJB if they are not read only. So, what about using ejbCreate(), setSessionContext() or setEntityContext() methods instead (not even sure this would be appropriate without more details on the problem you are trying to solve)?
The EJB container, for a #Singleton bean, shall create the instance of the bean as soon as the application is deploy if it is annotated #Startup.
That will, of course, fire up static initialization blocks, the constructor, dependency injection setters, #PostConstruct methods etc.
Here is the appropriate referente to the Java EE 6 Tutorial.
Related
I have a Java EE app that's deployed on WildFly AS.
I have a method annotated with #Asynchronous and I need to set the max number of threads for this method.
I configured a new <managed-executor-service> in server config, but I don't know how to bind it to an async method.
This link: https://developer.jboss.org/message/851027#851027
provides a good answer to how (or when) to use #Asynchronous and when to use JSR-236 ExecutorService and concurrency utilities:
In short, #Asynchronous is a annotation (EE6) to mark an EJB method as async.
You can invoke the method and keep the future object to check whether the method is finished and get the result. The EJB Concurrency Utilities are provided to have a safe way in EE7 to delegate work to a parallel thread. Threads started by this ConcurrentUtilities are managed by the container.
In difference to a direct start of a Thread (which is not allowed for an EE application). There is less overhead than using #Async and you have a bit more control.
See also this link about how to inject a MES:
http://www.adam-bien.com/roller/abien/entry/injecting_an_executorservice_with_java
ASP.Net 5 offers an options pattern to easily convert any POCO class into a settings class. Using this I can write my settings in json and then turn them into a typed object that I can inject into my controllers. So, for example, my ConfigureServices method in Startup.cs contains the line
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
and then this gets passed into my controllers' constructors using dependency injection
public ItemsController(IOptions<AppSettings> settings) { /* do stuff */ }
One of my controllers fires up a DNN to do some of its work. To reduce the cost of starting the DNN I do that from the static class constructor. Static constructors are parameterless and so I cannot pass in the required settings object, but I could set a static IOptions<AppSettings> property on the ItemsController from my ConfigureServices method. How do I get at that? Where is the dependency injector and how do I persuade it to hand me an IOptions<AppSettings>?
I think you are looking at the problem wrong. The problem is that you have a static class and are using DI, not how to inject your dependencies into a static class (which cannot be done without resorting to a service locator or another hack).
Most DI containers have a singleton lifestyle, which allows you to share the same instance of an object across your application. Using this approach, there is no need for a static class. Eliminate the static class by replacing it with an singleton instance, and you have an avenue where you can inject dependencies into your constructor.
I am using EJB in order to take advantages of:
Concurrent (instead of creating 2 threads, I divided the work into 2
EJB beans).
Pooling (I use stateless EJB a lot and I love the idea that the pool
contains a specific number of bean). This way, I am not afraid of
running out of memory. Memory usage is more predictable).
Asynchronous processing (all I need is just an annotation).
Well, the problem is I am using it with MongoDB so I don't need any transaction. I can use #TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) and #TransactionAttribute(TransactionAttributeType.NEVER) annotations but... it means I must specify it everywhere?
Is there anyway to disable EJB transaction by default?
In an EJB 3.0 container, annotate your EJB (or EJB method) with:
#Stateless
#TransactionManagement(TransactionManagementType.BEAN)
#TransactionAttribute(value=TransactionAttributeType.NEVER)
public class YourBean
for BEAN management. For CONTAINER management instead:
#Stateless
#TransactionManagement(TransactionManagementType.CONTAINER)
#TransactionAttribute(value=TransactionAttributeType.NEVER)
public class YourBean
The default value is managed by the container but if you dont specify nothing to do i think you solve your problem.
Or annotate all the Ejb to donĀ“t support transaction
#Stateless
#TransactionManagement(TransactionManagementType.NEVER)
public class YourBean
Remember that the ejb transactions are executed in a hierarchical way, ie if the first method being invoked does not support methods "children methods" are handled in the same way
Is it a good practice for a class to extend HttpServlet and implement ServletContextListener?
public Myclass extends HttpServlet implements ServletcontextListener {
}
What are the pros and cons of doing this?
Some thoughts:
You will have at least two instances of your class. The container create one as ServletContextListener and at least one as HttpServlet when your servlet get an incoming request.
Since the 2+ instances you cannot use instance (just static) members to share data.
It's easier if other classes don't use the data/objects that you initialize and share in the listener because you don't have to put these data/objects to the application scope in the ServletContextListener and retrieve them in the HttpServlet.
If your initialization logic is complex maybe it's worth to separate it from the servlet code (e.g. putting the initialization code to a different class and using the application scope to get the shared objects in the servlet).
It all depends on you, the implementer. ServletcontextListener has its particular purpose. Make sure you know what it is for before using it.
In case you are creating an HTTP servlet you must extend HttpServlet.If your class wants to "receive notifications about changes to the servlet context of the web application" (copied from javadocs) it is part of, you have to implement ServletcontextListener.
In EJB 3.1 I can get all timers for a specific bean using TimerService#getTimers() on the TimerService instance obtained for that bean.
What I actually need however is a system-wide version of this. I.e. I would like to have a list of all Timers in the EJB container.
Is something like that possible?
There simply is no official API for this in EJB 3.1.
If you're only using annotations and/or interfaces to mark your timeout method, you could do a run-time walk over all classes on the class path and check if this annotation or interface is present. This will at least give you the beans which theoretically can have timers associated with them.
Unfortunately, this still won't give you the actual timers for those beans. In EJB 3.1, the time information can only be requested from the session context, which as you already seem to know is private for each bean. This means that only the bean itself can see what timers it has.
As an alternative to what Nayan is suggesting, you could let your beans implement a method that gives you this info. You can then mark this method with either an interface or a custom annotation.
In your system-wide sweep over all timer classes you first try to discover all beans that can have timers associated with them, and of those you then try to find whether they have the required annotation or interface. If they don't have this latter thing, you can log a warning. The advantage of this method is that it's less likely that timers slip through the cracks.
Yet another method, but a very brittle one, is to hack into whatever private structure the container holds to store the timer information. For persistent timers there is at least the persist store which you can check, and somewhere in the container there must be the structure you're after. It must be there as the container itself has to be aware of this. Often a container has some private API to get to this and you can hack into that via reflective tricks.
It can also be that containers offer a proprietary API for this. E.g. in Java EE 5 it's impossible to do a programmatic login in the Servlet container, but JBoss AS has a proprietary API that allows you to do exactly that.
EJB 3.2 has a method called "getAllTimers()".
https://docs.oracle.com/javaee/7/api/javax/ejb/TimerService.html#getAllTimers--
Description:
Returns all active timers associated with the beans in the same module in which the caller bean is packaged. These include both the programmatically-created timers and the automatically-created timers.
Below is the sample code fragment for fetching information of all the existing timers of the system.
//---
private void viewSystemTimers(){
Collection<Timer> allTimers = sessionContext.getTimerService().getTimers();
Iterator<Timer> iterator = allTimers.iterator();
while (iterator.hasNext()) {
Timer timer = (Timer) iterator.next();
System.out.println("SYSTEM TIMER : "+timer.getInfo());
}
}
//---
You can only see timers of your own class. With the EJB Scheduler you can't list all timers of your application.
#Resource
private TimerService timerService;
for (Timer timer : timerService.getTimers()) {
// do anything
}
With Quartz you can via Scheduler.getJobNames/triggerNames for all jobs/triggers of you application.