Call method after JBoss deploy - java

I want to have some method run, only after my WAR has been deployed to JBoss.
The problem: Currently I am using #PostConstruct to load saved schedules from the DB. The problem is that I am creating instances of the Schedulers from this method, which in turn is starting the Quartz schedulers, which is stopping JBoss from completing the deploy.
If there are no schedules to load, my WAR deploys fine, but if there are schedules they are causing the deploy to fail, because JBoss is "waiting" for the schedules to actually complete.
Is there some way to delay the method call until after it is fully deployed?
Or alternatively, is it possible to make Async calls on the Server (from the Server code)?

Java EE specification heavily refrain any thread manipulation outside facility provided by the application server.
You shouldn't in any case use a container manged thread in an infinite loop; the container expect the thread to be returned. Thread creation can still be done without too much collateral damage (if you don't put several apps on the server as the container won't be able to manage the resources between all the applications) but the any container thread must be returned.
In the new Jboss 7 there is some Java EE scheduling facilities (#Scheduling and timer, with possible persistent timer). A quick search show some example how to run Quartz in JBoss 7: How to enable Quartz scheduling in Jboss AS 7.0?
In older JBoss more advanced integration exist (JCA integration is the only standard way to get finer thread management). Use google to find them.

Wouldn't the simple ServletContextListener solve the problem for you? Just implement whatever you need in contextInitialized method.

In JBoss 7, there is a management api.
Maybe you can use it to check if the server is started (with a singleton and a TimerService).
Sample code:
ModelControllerClient client = ModelControllerClient.Factory.create(InetAddress.getByName("localhost"), 9999);
ModelNode op = new ModelNode();
op.get(ClientConstants.OP).set("read-attribute");
op.get(ClientConstants.NAME).set("server-state");
ModelNode returnVal = client.execute(op);
if(StringUtils.equals(returnVal.get("result").toString(), "\"running\"")){
LOGGER.info("Server running, init start actions");
timer.cancel();
}else{
LOGGER.info("Server not running, wait");
}

Related

Springboot: need to be informed/notified when Web-Server is Up

I am writing a Springboot application embedding Tomcat as a Web Server.
At startup, some of my threads are ready (and so start doing their job) before Tomcat is. For many contraints I have, I want that these threads do nothing before Tomcat is ready
But I don't know how to decided to block/unblock my threads; to do so, I need to be informed of the Tomcat status. Is there:
a way to ask: isWebServerStarted()?
or a way to be notified asynchronously by a message saying: WEB_SERVER_IS_STARTED?
Thank you for help
FYI, I don't want to declare a kind of "private ReST endpoint" that my
application could try to reach in order to guess whether the webserver
is ready
Go with a ServletContextListener. Annotate your class with #WebListener and tell spring configuration about this listener by adding #ServletComponentScan annotation.

Difference between ManagedExecutorService and ManagedThreadFactory in Java EE

Our current legacy web-app creates threads in it not managed by Application Server Containers. I have to modify it with JavaEE standards for multi-threading.
My web-app works fine on Tomcat but fails on Websphere.
Error on Websphere :
... ... Caused by: javax.naming.ConfigurationException: A JNDI operation on a "java:" name cannot be completed because the server runtime is not able to associate the operation's thread with any J2EE application component. This condition can occur when the JNDI client using the "java:" name is not executed on the thread of a server application request. Make sure that a J2EE application does not execute JNDI operations on "java:" names within static code blocks or in threads created by that J2EE application. Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on "java:" names.
at com.ibm.ws.naming.java.javaURLContextImpl.throwExceptionIfDefaultJavaNS(javaURLContextImpl.java:534) ~[com.ibm.ws.runtime.jar:?]
at com.ibm.ws.naming.java.javaURLContextImpl.throwConfigurationExceptionWithDefaultJavaNS(javaURLContextImpl.java:564) ~[com.ibm.ws.runtime.jar:?]
at com.ibm.ws.naming.java.javaURLContextImpl.lookupExt(javaURLContextImpl.java:485) ~[com.ibm.ws.runtime.jar:?]
at com.ibm.ws.naming.java.javaURLContextRoot.lookupExt(javaURLContextRoot.java:485) ~[com.ibm.ws.runtime.jar:?]
In order to resolve this issue, I am referring Concurrency Utilities in Java EE. I found similar kind of description and example for ManagedExecutorService and ManagedThreadFactory.
ManagedExecutorService: A managed executor service is used by applications to execute submitted tasks asynchronously. Tasks are
executed on threads that are started and managed by the container. The
context of the container is propagated to the thread executing the
task.
ManagedThreadFactory: A managed thread factory is used by applications to create managed threads. The threads are started and
managed by the container. The context of the container is propagated
to the thread executing the task. This object can also be used to
provide custom factories for specific use cases (with custom Threads)
and, for example, set specific/proprietary properties to these
objects.
Which one is preferred in which condition and why ?
I have solved issue by using ManagedExecutorService.
ExecutorService framework indeed has more ways to deal threads while ManagedThreadFactory can only call newThread() method.
Websphere issue can be resolved by using ManagedExecutorService or ManagedThreadFactory. Both works. But for further thread processing, ManagedExecutorService turns out lot better.
Now, this solution causes same web-app to fail on Tomcat. JNDI naming exception. As per my R&D, container based concurrency is supported in TomEE server not in Tomcat so we have to use routing mechanism to switch between code as per underlying application server.

Parallel Tests with Jetty and Weld

I want to execute unit tests on an embedded Jetty with CDI/Weld in parallel in the same JVM.
For every test method a new jetty instance with a clean database is created. Execution in sequence works, however, in parallel I'm running into an exception.
org.jboss.weld.exceptions.DefinitionException:
Exception List with 1 exceptions:|Exception 0
:|java.lang.RuntimeException: javax.naming.NameAlreadyBoundException:
com<|?at com.sun.jersey.server.impl.cdi.CDIExtension.initialize(CDIExtension.java:196)
The full stacktrace is at pastebin.
The servers and context are isolated on different jetty server instances and ports. However, Weld does not realize this, although it detects a Jetty container and seems to be using a shared state some place (maybe this is Jetty specific?).
Has anyone come across this problem or has a tip how to tell Weld that it should not register twice?
You could try to fork on every test, so they're all done in different JVMs. It looks like Weld is storing beans per JVM (which makes sense) and when a new server is being started its running through the bootstrap again.

stopping threads gracefully

I am using ScheduledExecutorService for scheduling a thread. I wonder what happens when JBoss is shut down? Does it kill all the threads that are started within the server, including the the one I scheduled? Do I have to do it manually using ScheduledFuture, and cancel the thread when ServletContext is destroyed?
There are two methods:
java.util.concurrent.ExecutorService.shutdown()
java.util.concurrent.ExecutorService.shutdownNow()
JBoss won't call any of these unless you do it in method which will be called upon shutdown. For web applications you have the chance to do it in javax.servlet.ServletContextListener.contextDestroyed(ServletContextEvent).
Of course this is the JavaEE/Servlets way. You can hide it by using e.g. Spring Framework. By creating org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler you'll get shutting down for free (this class implements org.springframework.beans.factory.DisposableBean). See the details here.

Spring: Is there a simple non-web tutorial?

I'm attempting to create a Spring application (NOT web application) to perform some simple tasks. Eventually they will hook up with some other Spring apps around the network, but for now I'm keeping it simple. I have a CheckForNewItems class (extending Timer) which is configured to run every 10 seconds.
I can confirm it runs by calling it programmatically:
public class Tester {
public static ApplicationContext context;
private void loadContext() {
String filename = "beans.xml";
context = new FileSystemXmlApplicationContext(filename);
}
public static void main(String[] args) {
Tester test = new Tester();
test.loadContext();
CheckNewItemsTask task = (CheckNewItemsTask)context.getBean("checkNewItemsTask");
}
}
Running this works as expected, task.run() gets called every 10 seconds. Now I need to work out how to deploy this to either a JBoss or Tomcat server, in such a way that it automatically starts running the task.
Most of the tutorials I've found only describe how to get Spring MVC and servlets running, not a standalone application. Does anyone know better?
Cheers, Rob.
You don't need JBoss or Tomcat to do that. If the app is headless and you have no intention of adding a UI, consider jsvc for unix or procrun on windows. If you need the ability to monitor and control an app and do not need a proper UI for doing that, you might want to look at JMX. This will work on a daemon without the rest of the Java EE stack.
If you have a maven project and want an easy way to turn it into a deployable daemon app, you can use maven appassembler to automate the process of creating a deployable daemon, setting up a directory structure of the app, scripts to start and stop, libraries and config files.
You need a servlet that is set to autostart on deployment. The servlet can then call into your "Tester" class to trigger your "standalone" initialization process.
If you don't have a servlet (or potentially some other server related process) reference your code, then your initialization process will never be run.

Categories