Perform operations at the end of a JBoss 7 deployment - java

We have an application that needs to do some initialization at the end of a deployment (in a JBoss 7.1.0 instance) because only then will all the required services be available (there are quite a few of them).
One approach we tried was this:
We have a singleton service along with an #Startup annotation but we so far were not successful in telling JBoss to create the instance last without too much hassle.
We could use #DependsOn but we'd have to maintain an ever growing and already large list of dependencies and thus we'd rather do that only as a last resort.
In the old days (JBoss 4 and 5) there was a possibility to define a dependency on the application (like #Depends("myapp.ear")) which causes exactly what we need.
As of JBoss 7 things have changed but I assume there's still a way to do that.
Another approach was to try and create our own JBoss subsystem which is invoked after all other subsystems are started but we were not able to find a way to wait for the other subsystems to finish before performing the operations we need.
What other options could we look into?

You could put a class annotated with #Startup into a different EAR, or better WAR. A WAR will - I think - by default be deployed after any EAR without having to configure anything.
In the startup class, you can just invoke the actual initialization, which is deployed together with the rest of your application with myapp.ear. The invocation is done through an EJB local or remote interface.

You can have a servlet e.g. BootstrapServlet.java, defined with the setting load-on-startup>1 /load-on-startup> in your WEB-INF/web.xml and do the initialization in that servlet.

Related

CDI extension, how to know the Application name that a bean belongs to

I am new to CDI and I am writing a new CDI portable extension. My CDI extension will listen to events that are fired by the CDI container. I was wondering if there is a way to tell the name of the application that a class belongs to and what are the events that would provide that information.
by application I mean a ear application archive that is deployed on an application server. My goal is to create an extension that looks into applications deployed and for each add an annotation on some of it's classes. Each application classes would have a unique annotation. Example if we have app1 and app2 deployed on an app server. I want to create an extension that would annotate all/some classes contained in app1 with with #x1 and all classes of app2 with #x2 and so on.
To my knowledge, there is no concept of application in CDI. There are only bean archives. You might be able to determine that - e.g. WAR1 will be a different bean archive than WAR2 which in turn will be different than EAR/lib.
BUT, and I cannot stress this enough, the bean archive concept is interpreted slightly differently in Weld and OWB (as CDI implementations) so sticking to this would make in unportable (which probably won't matter since all servers except TomEE use Weld anyway). Truth be told, to even get hold of a bean archive, you might have to rely on Weld API (not just CDI).
But I think it would be wiser to find another way around this - why are you trying to achieve this? What gain is there in annotating beans differently in different archives? Because #Nikos has a good point with class loading. There is a whole new level of mess with EARs and you won't "see" some bean from other archives anyway (as per Java EE umbrella spec).

Can multiple portlets share a singleton? [duplicate]

I have a couple of Singleton classes in a Liferay application that hold several configuration parameters and a ServiceLocator with instances to WebServices I need to consume.
I have put these classes in a jar that is declared as a dependency on all my portlets.
The thing is, I have put some logging lines for initialization in theses singleton classes, and when I deploy my portlets I can see these lines multiple times, once for every portlet, since each portlet has its own class context.
For the AppConfig class it might not be such a big deal but my ServiceLocator does actually hold a bunch of references that take a good bit of memory.
Is there any way that I can put these Singleton references in some kind of Shared context in my Liferay Portal?
The problem is that every Portlet runs in its own WAR file and aech war file has its own classloader.
Usually when I had to achieve a requirement like this, I had to put the Singleton classen in a JAR file and this JAR file in the common class loader library instead of packing it into each WAR. (In Tomcat: <tomcatHome>/common/lib or something like that)
Then you'll also have to put all dependent libraries into that common lib dir, too. Don't know how to do that in Liferay, though. For tomcat see this thread: stackoverflow.com/questions/267953/ and this documentation: http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html. Depends on the Servlet container.
Alexander's answer gives the general answer that's true with or without Liferay in mind.
Liferay (as you mention it) adds another option to this: ServiceBuilder. You'll end up with the actual instances contained in exactly one web application, and you'll have an interfacing jar that you can distribute with every dependent application. This way you can more easily update your implementation: It's easy to hot-deploy new and updated web applications to your application server - it's harder to update code that's living on the global classpath.
The global classpath (Alexander's answer) however brings you immediate success while ServiceBuilder comes with its own learning curve and introduces some more dependencies. I don't mind those dependencies, but your mileage might vary. Decide for yourself
With maven portlet you can make a common Spring component and import in the pom of each portlet.
Another solution is to use service builder.
Spring MVC portlet would be the most recommended for this.

Run main method in EJB on Deployment of EAR

I have created one java project which has one Main class. So I am running this Java Project using this Main class main method . But now my requirement is changed that I have to create the EJB of this project, and deployable artifact will be EAR. So still in the search of that how i will run this main method on the deployment of this EAR in Websphere.
Just want to summarize that I want to execute main method in EJB on the deployment of EAR in WebSphere, searched a lot try one or two methods but still searching for some good way.
From your question and comments it is not entirely clear to me if you fully understand how EJBs work (i.e. their lifecycle, how they get called, etc.). If you haven't done so, I recommend reading a Java EE tutorial, e.g. this one from Oracle.
Once you have an overview how things work, have a look here and choose the way which fits best for your case.
Common to all ways is that you cannot have a main method as before, but you have to convert it to a normal public method of your EJB which will get called at startup.
Since you are using and EAR anyway, you can also package a WAR inside the EAR along your EJB, and then use the ContextListener method described in my link.
But also nowadays there is almost no need to have an EAR. You could package everything in a WAR. See here: Why use an ear instead of a war?
As far as I know, if you're on Java EE 6 and you want your EJBs methods to be called in a scheduled manner, you can make a scheduler EJB by annotating it with #Schedule, inject your EJBs in it and make the scheduled method to call your injected EJBs methods. If that's not the case and you want to call them on demand, you need a client like a Servlet in which you inject them.

How to inject a CDI managed bean that exists in another classloader

I am working on a framework which will be used in Java EE applications and therefore is likely to be deployed in the \lib directory of an EAR file.
The framework will use CDI to programmatically lookup and inject beans that are located in the Java EE application that is using the framework. The problem I've got is when the Provider.get() method from javax.enterprise.Provider<T> is called by my framework to get an instance of the bean, Weld throws a UnsatisfiedResolutionException.
To check this isn't an issue related to CDI I've also tried using MyClass myClass = Class.forName(clazz).newInstance(); to get an instance of the class but a ClassNotFoundException is thrown.
The structure of EAR file I'm using for testing purposes is as follows:
MyTestApp.ear
+\lib\MyFramework.jar <----Contains the framework invoking the Provider.get() method
+MyTestApp.jar <----Contains the bean I want to inject
My test application's EAR contains an application.xml file which includes <library-directory>lib</library-directory>.
I believe this problem is occurring because the bean I want to inject exists in a separate classloader. i.e. \lib\MyFramework.jar is in a different classloader to MyTestApp.jar. I found this SO question which seems to suggest this is the case. Given that I'm developing a framework I don't believe the answer in the question is a viable solution for my needs.
I'm intrigued to find out whether creating a CDI portable extension would allow me to get an instance of the bean I want to use, but don't have enough experience in this area. Using #Observes ProcessAnnotatedType<T> I can see beans that exist outside of the \lib directory in an EAR file, including the ones I want to programmatically inject.
My questions are:
Am I correct in assuming this problem is occurring because \lib\MyFramework.jar and MyTestApp.jar are in separate classloaders?
Is there anything I can do using CDI that will allow my framework when deployed in the \lib directory of an EAR file to make the Provider.get() method call to avoid Weld throwing a UnsatisfiedResolutionException?
Is there anything I can do outside of CDI to achieve same result?
Update
I've now tried moving MyFramework.jar to the root of the EAR file and also including the jar module in the application.xml file but the container fails to start the application due to a CDI unsatisfied dependency exception. The bean referenced in the exception can be injected when MyFramework.jar is located in the \lib directory and is a different bean to the one referenced in my question.
1 : yes
2 : actually I don't know
3 : Yes, you must understand the ear classloader hierarchy, the jars in ear lib directory are loaded at the ear level and so available in all child classloaders (there is one child classloader per component in the ear).
It means that MyFramework.jar is visible from MyTestApp.jar ear child classloader but the inverse is false.
see In java EE, which jars should I put in the library dir?
You can either :
move MyTestApp.jar to ear lib directory (MyFramework.jar can be either in lib dir and reference MyTestApp.jar or at ear root)
move MyFramework.jar at ear root and reference MyTestApp.jar in its manifest classpath
see Deployment of multiple, depended CDI jars in one EAR
It seems to me that it might be a poor architectural decision to have your "framework" depend on your application implementation. Perhaps it should be that your application that implements some framework-level interface to achieve your goal. As you have it, or would like it to work, suggests that an application, any application really, in your ear could influence the operation of all other applications in your ear by providing implementation to the framework. This seems like a bad idea to me. And if you were able to make this work and more that one application in your ear provided this implementation, CDI may still fail because of ambiguous dependencies.
There may be some container specific dependency configurations that you might be able employ. WildFly, for example, allows you to configure module-to-module dependencies. I think, it might be possible, in WildFly, for an ear to depend on a war.
While the above might work, after thinking about it, I this it is also a bad idea. You should really take a hard look at what you are really trying to do. I think if you take a harder look at what you are trying to do, you will discover that your will probably be able to peal out or abstract some dependencies and still provide implementation to the framework, but not from the applications in the ear.

Load spring context in phases

This is one of those strange questions where people would ask - why?
So I will start with why I would like to do this and then go into the issue. I would like to have more control over how the spring context is loaded. For example, I do not want to load the domain and web-api at the same time. That would make the resources available before their dependencies are ready.
There might also be that I need to check the state of something before I can continue this process. So to say, there will be sequential order between modules/contexts. Maybe not just booting but also in shutdown.
So the issue is that I can't find any information on how to load the domain-context, then when that is finished I would check the state and lastly load the api-context. I would like to do all of this from java-code as I need to control the flow of the start up. I have basics working with SpringServlet loading the web-context. What I have not found any information on is if it is possible to load a context, wait and load another context that refers to the first one.
It might be good to know that I am not using JavaEE nor a container. I am only using embeddded Jetty with servlet and spring. So is there a way this can be done?
I'd suggest to consider following:
Read SmartLifeCycle and Phased for extension points on the order of application context life cycle management. The idea is that you have your top-level important beans implement the interfaces such that the standard application context initialization will be also handled to those beans in the order that you customize.
Break your application context XML files into smaller pieces. Use <import /> in the ones that depend on a higher/lower context.
Use depends-on attribute on your mission critical beans to ensure the dependencies.
Use InitializingBean on the ones that you need to make sure a dependency is satisfied for the current bean after it's initialized.
Consider lazy loaded beans and Lazy Proxy.
So the bean will be created only on first usage ...

Categories

Resources