Trigger ApplicationListener before WebServer starts - java

I have a short lived process to read a simple file from a classpath into a memory, I chose ApplicationListener<ApplicationReadyEvent> to let spring trigger a task:
#Component
#Priority(1)
class MyLoader implements ApplicationListener<ApplicationReadyEvent> {
#Override
public void onApplicationEvent(ApplicationReadyEvent event) {
doStuff();
}
}
I realised not that few HTTP requests that I offer in this app depend on that data in memory. How can I force MyLoader class to execute before Web Server is ready to serve request? I have no idea how to define that dependency?

You should listen for an event before the ApplicationReadyEvent, because it is the final one, marking that the application is ready to serve requests.
For example, you can listen to ApplicationStartingEvent. See a list of the available ApplicationEvents here.

Related

Is it possible to activate or deactivate jobs via a configuration file so as to avoid unintentional startups?

I would like to have the possibility to activate or deactivate jobs via:
a configuration file with specific ON/OFF for each job or
a mysql table with specific ON/OFF for each job.
Charging must take place at each change of status: for example, if a job is OFF when the ON setting (state change) the java app will be able to receive the status update.
Thanks for helping me out.
If I understood your question correctly, you are looking for capability to control your jobs from configuration. If yes, then following might be helpful.
You can schedule you jobs using Apache Camel routing.
public class JobExecutorRoute extends RouteBuilder
{
private String script="exec:yourjob.sh";
private String cron="quartz2://group/timer?cron=00+00+010+*+*+?" ;
public void configure() throws Exception {
from(script).autoStartup(true).to(cron);
}
}

Threads in spring: synchronized or #Scope("proptery") performance

I have two spring beans. A JmsHandler which receives a Message. This is processed and handed over to a MailHandler which sends a mail. Now I've seen that sometimes messages arrive at the JmsHandler in exact the same time. When entering the sendMail method one of the both isn't processed properly (no mail is sent). So I would expect that's an threading issue.
I've got two possiblities to handle this issue:
a) I set the sendMail method as synchronized. Which means the next execution will be stopped until the first is processed.
public class JmsHandler {
#Autowired
private MailHandler mailer;
public void handleMessage(Message msg) {
mailer.sendMail(msg.getPayload().toString());
}
}
#Component
public class MailHandlerImpl implements MailHandler {
#Override
public synchronized void sendMail(String message) {
// do some fancy stuff...
// do something to mail the message.
}
}
b) I define the MailHandler to the scope "prototype" and get it using an lookup from the ApplicationContext.
public class JmsHandler {
#Autowired
private ApplicationContext ctx;
public void handleMessage(Message msg) {
MailHandler mailer = ctx.getBean(MailHandler.class)
mailer.sendMail(msg.getPayload().toString());
}
}
#Component
#Scope("prototype")
public class MailHandlerImpl implements MailHandler {
#Override
public void sendMail(String message) {
// do some fancy stuff...
// do something to mail the message.
}
}
I think both ways are ok. But in terms of performance is there any issue? When using synchronized it will stop execution of the next process and wait until the first is finished. The second will create a new Instance of MailHandlerImpl when a message has to be send (and of course autowire other things not shown here).
Or is there a third alternative?
The only way to spot performance issue is to get a metrics about your application behaviour. You should see metrics and better use Timer so that you can see how many message has been handled and how fast it is processed. It's awesome.
If you are certain that mail handler is only capable of sending an email in certain moment, just make sure you only have one consumer. No need to use synchronized. If you prefer concurrent process/ multi consumer, which is generally preferred, create mail handler for each thread. Leverage reactor to ease your parallel processing (use thread pool executor in your event bus) and commons pool to hold your mail handler instances. Thread pool executor size and your mail handler pool size should be equal. Or, you can use email service such as mailgun to ease your concurrent email sending.

How can I close a SpringBoot WebSocket server?

I imagine it's incredibly simple but I've been unsuccessful in my googling of how-to's, reading of documentation, and perusing of Spring classes.
Spring's doc on their websocket api has been useful and I can see that the project I'm familiarizing myself with uses what it describes to start a server:
#Configuration
#EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
#Autowired
private MyWebSocketHandler webSocketHandler;
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(webSocketHandler, "/");
}
}
So it's easy enough to start, but I have no idea how to make it stop or pause. I'd like to add a feature to the application that takes down the server (and re-establishes it later) with a click of a button. But I have no ideas about how to stop or pause the server and the documentation doesn't seem to offer anything.
the initialization/management/shutdown of websocket/http connections are handled by spring and tomcat (default). I don't think it's a good idea to deal with it on your own.
a solution would be to decouple (with two springboot apps) the websocket service (which can be started/stopped manually) from the one (which is always up and running) with the "click of a button" page.

wildfly have a ever running process run in the background

I'm making a html5/js game that will have online capabilities for my backend I've decided to use a wildfly server. The client will communicate with the server via web sockets.
I intended for my wildfly server to also be in charge of game logic decisions such as moving npc's. My plan was to have a #startup bean that would run a server game loop to handle this logic. The server loop would then talk to the serverEndPoint via HornetQ. My serverEndPoint and server loop look like this:
ServerEndPoint
#ServerEndpoint(value= "/game/{user-id}")
public class GameEndpoint {
#Inject
GameManager gameState;
GameWorld gameWorld;
Player p;
private Logger logger = Logger.getLogger(this.getClass().getName());
#OnOpen
public void onOpen(Session session){
//do stuff
}
#OnMessage
public void onMessage(Session session, String message){
//do stuff
}
#OnClose
public void onClose(CloseReason reason){
//do stuff
}
#OnError
public void error(Throwable t){
//do stuff
}
}
GameWorld
#Startup
#Singleton
public class GameWorld {
#Inject
GameManager gameState;
private Logger logger = Logger.getLogger(this.getClass().getName());
#PostConstruct
public void init(){
gameloop();
}
private void gameloop(){
while(true){
logger.info("This is a test!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#PreDestroy
public void terminate(){
//do stuff
}
}
the issue with this is that the server loop freezes everything as it is a infinite loop(for instance if I try and access the html web page I get a 404). obviously this could be solved if the serverLoop was on its own seperate thread but after doing some research it seems threading in jboss is very difficult as its hard to know what dependencies to inject e.t.c
Can anyone shed some light on how I can solve this issue? any help on the matter would be amazing.
What you have encountered has to do with what Java EE is and what it not is: Java EE is optimized for handling many concurrent, short-lived requests, each of which (usually) handle a single transaction. The containers do that very well, particularly with stateless beans, but also with stateful beans (cluster replication etc). As such, Java EE might be well-suited to process the requests coming from your HTML5/JS clients and feed the requests to the messaging infrastructure. Java EE is not, however, designed for long running, thread-blocking background processes like yours.
FWIW: Another issue that you have not yet encountered is, even if you could get that one fixed: Next you'll encounter the transaction timeout on your #PostConstruct method.
I think you are better of with moving the game engine out of the Java EE stack. You already mentioned you plan to use HornetQ - then why not put the game engine in a simple standalone application that receives messages from HornetQ and feeds replies back into HornetQ.
Another option might be a dedicated Java game server engine, see, e.g., this question and its accepted answer on programmers.stackoverflow.com. (Update: it seems the "RedDwarf Server" project mentioned in that answer was discontinued 3 years ago).
If you absolutely want to use the Java EE environment, I suggest you use a TimerService instead. Note, however, that this also requires that your game loop calculation is quick and guaranteed to finish until the next timeout is scheduled, otherwise the container will skip the scheduled invocation (with a "still running" message or similar).
Finally, let me mention that if I were to start a new game server today, I would definitely take a look at Akka, Node.js or similar projects that support "reactive" programming.

Java TCPIP EJB Threads

I am developing a TCPIP application where the client will send information to a specified port and the server will listen to that port. I would like to achieve the following:
Reconnect to the the client/port to see whether it is active after a specified time period.
I have the below code implemented:
#Stateless
#Local
public Listener implements ConnectionListener {
public void listen() throws Exception {
ServerSocket serverSocket = new ServerSocket(somePort);
Socket socket = serverSocket.accept();
while(!socket.isClosed()) {
}
}
}
public interface ConnectionListener {
public void listen() throws Exception;
}
How can this be achived with EJB technology? I know the while loop is wrong but what can be included. I have two approaches:
Wait for a time period to reconnect
Thread
However, I do not wish to use the Thread appraoch.
I know in EJB there are things such as an EJBTimer. What would be the best way to implement this and how could this be implemented in the code. Could you help how I could change the while loop to do what I want it to do?
Also, the client has no API to call on this application. How can this instance be triggered on start up of the Application Server so that messages are listened to. Usually, this could be achieved through a Servlet but I don't think this will work. Any ideas?
This kind of functionality is at the "edge" of the types of things you would do in EJB. typically, EJBs do not directly do network type activity, especially long term listening.
what you really want is an EJB singleton. this is kind of like a standalone instance which can do more advanced things like custom concurrency/threading and (relevant to you) start a custom socket listener.

Categories