For my Spring-based web application, I now have the requirement to send out weekly e-mails to my application's users.
What are elegant solutions to this requirements?
Up until now, I have come up with the following possible solutions:
a dedicated cron job that I schedule to run once a week, running independently from my web application JVM process and outside of the web application Servlet container. This process takes care of sending out those weekly e-mails. To accomplish sending personalized e-mails, it reuses domain classes (such as my User class) that I have already developed for my web application. This dedicated process accesses my application's MySQL database concurrently to the running Spring Web MVC servlet?
a scheduled mechanism inside my Spring Web MVC servlet or inside my Servlet container.
In this setup, the e-mail sending happens inside the same JVM and the same servlet container as my web-serving Spring Web MVC servlet. Maybe this setup has (irrelevant?) advantages such as "database connection pool sharing" and "transaction sharing" "class sharing" with the servlet hosted inside the same environment.
Using or not using Spring Batch, for any of the above conceived setups. I have no experience right now with Spring Batch as to judge whether Spring Batch is or isn't an adequate tool for my requirement.
Maybe there are other solutions as well?
I am especially interested in answers that can give insights and guide in making an educated decision.
It is irrelevant for this particular question whether e-mails get sent with my own infrastructure or with a third party e-mail SaaS service.
From your description, the code for generating newsleters must share common code base with your main application. So the natural solution is to develop this code withing your main application. The open case is how this code is triggered:
From CRON. You start a script from CRON that would trigger the function within you application somehow. This somehow may be a process listening on specific port, or, what is quite natural for web application, a dedicated URL that would trigger newsletter. Just make sure that URL can't be run from outside, only from localhost (check caller IP, for example). You must, however, deal with the situation, that your app is down (restarting for example) when CRON launches the script.
From within the application. For example, using Quartz. The minus is that you need to include new library, create database tables for Quartz. The plus - Quartz will handle situation, when the task was scheduled on the moment when the application was down, because it stores the information about what was launched in DB.
We always use cron to fire a JMS message to a queue and have a dedicated process which consumes these messages. You can add the email contents to the message or just use the message as a trigger. The nice thing about this approach is you can fire in a JMS message from anywhere and have multiple handlers lots of different email scenarios. The only downside is installing a JMS broker, if you don't already have one...
I am building a Spring-MVC based web application which is required to send a weekly newsletter to a small group of people. I am using Spring's built-in scheduling mechanism. http://static.springsource.org/spring/docs/3.0.x/reference/scheduling.html‎
Yes, in this setup, the e-mail sending happens inside the same JVM and the same servlet container and it is quite easy and handy to implement the solution. I am observing the stability and reliability of this mechanism and cannot feedback more about it now.
Related
I want to run cron jobs and use the same code base. I found a few solutions, but they don't appear ideal. For example, with Heroku, you can add a Scheduler element and fill in the commands to run in a web page.
http://blog.rotaready.com/scheduled-tasks-elastic-beanstalk-cron/
It seems overly complicated for load-balanced instances.
It makes use of require('async') in Node, but what would be a Java Spring Boot equivalent?
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features-managing-env-tiers.html
There doesn't appear to be any security. Any one the net could access the /path to POST and execute the job, causing a denial-of-service attack.
it mentions cron.yaml which doesn't make sense as the app is deployed via a WAR/ZIP file to a Tomcat instance (Spring Boot).
It mentions Amazon DynamoDB, which we don't use. We use MySQL.
It doesn't specify whether the load balancer connection draining timeout is in effect for these jobs (10s).
It mentions "Worker Configuration card on the Configuration page in the environment management console" but there is no Worker Configuration card under Configuration page.
Running a cron job in Elastic Beanstalk
For Python/Django - uses cron.yaml.
I thought of just having a dedicated EC2 instance, but how can I deploy the latest code changes there?
This may also belong on SoftwareEngineering.StackExchange.
There is an easy way to do this using other AWS systems.
You can use CloudWatch to set scheduled events (https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/WhatIsCloudWatchEvents.html). You can set a rule to set the event on a set schedule.
You then have at least two options:
set the event to publish an SNS message and use that SNS to call a web hook on your server. Many examples on how to do this but you will have to make sure you check the signature to ensure the web API is called from the signed SNS. But this would use a public API and may not be something you are comfortable with.
set the event to publish an SQS message. Then set an elastic beanstalk worker to process the SQS message or just run a background script on your main server, which is basically on an infinite loop polling SQS for work to do.
Not sure how familiar you are with these systems so not sure if it will be clear what I am talking about, but there is no way to give a detail solution so hope this is enough to give you ideas.
I am looking for a better logical solution of a situation where one core Java EE (Web) application will call/execute many other Java applications/workers (which can be core Java or J2EE(web) application (don't know what will be the best)) at a certain time.
Those other Java applications/workers will basically connect (individually) with different Data sources (can be from remote DB or REST or SOAP, etc...) and populate/update local DB at a certain period of time.
I was doing research on Java Quartz Scheduler recently. Do u have any good suggestion to me for this Enterprise level architecture?
Btw, I am using Spring 4, Java 7
Thank you as always for all good and professional ideas.
Sample diagram can be as follows:
You can connect your java application with others easy with spring's httpInvoker or rmiInvoker.
More information here: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/remoting.html
Not sure to understand good, but you can look at a messaging mechanism. Typically, the WebApp will send a message that will be received by all the Workers.
Have a look a JMS which it designed for this kind of use, and integrates well with both JEE (it is a part of the JEE spec) and Spring.
There are basically two parts to your question:
How do I schedule jobs on a Java EE server?
How do I invoke remote services from that scheduled job?
Job Scheduling
The trick with job scheduling in a Java EE environment is that you are typically running jobs in a cluster, or more than one server. Thus, only one of the nodes should be running that job at a time "on behalf of" the cluster, otherwise, you'll get multiple calls to those remote resources for the same thing.
There is a standard out there for this, JSR-237, which covers Timers and WorkManagers. Each Java EE vendor has its own implementation. WebLogic has one, WebSphere has one, and JBoss has one (the JBoss one isn't compliant with the JSR, but it does the same thing).
If you are running one of the servers that only runs the web tier of the Java EE spec (i.e, Tomcat or Geronimo), then Quartz is a good choice.
How to invoke remote services from timed jobs
Echoing #Alexandre Cartapanis' answer, probably what you'll want to do is create a JMS Topic in your Java EE server, and then when the job runs, post a message to the topic. The remote services (whatever Java EE servers) subscribe to this topic, and then you can run your queries.
The big advantage here is that if you ever need to add another service that needs to populate the local DB, all you have to do is have that server subscribe to the topic - no code changes needed. With JSch or remoting, you'll have to make a code change every time a new service comes online. You also have to make code changes if DNS addresses or IP addresses change, etc, where as the JMS way is just configuration on the server. There's a lot more that you can do with JMS, and the support is much better across the board.
Spring has adapters for Quartz and I think there's one out there for WorkManagers and Timers too.
You can make use of JSch - Java Secure Channel to trigger remote ssh calls which can start a JVM and run the Worker class.
Here are some examples.
We have a requirement to allow users to generate search result exports in various formats. The problem is that the size of the exports can vary and take several seconds to minutes to complete. I want to allow users to be able to fire the request and continue doing other things while it runs, but I don't want to impair the web application server's performance by using background threads if necessary.
My initial idea is to decouple the web application and the generation process. I could use JMS with a message driven bean (MDB) that handles the file generation that is deployed separately from the web application; allowing to scale them individually based on future needs.
Technically, I see the web application maintaining a list of requests that it has started and sent JMS messages for. As the MDB completes, it sends updates back to a queue the web application listens on and updates the list of requests accordingly with status and perhaps file URI information. When user want to download a generated file they requested, the file is streamed to the browser and then removed.
As an added precaution, the MDB would also fire a delayed message into a cleanup queue that after the delay has expired, the MDB checks the URI of the generated file and if it continues to exist, removes the file and notifies the web application so it may update it's internal list accordingly perhaps by removing it or marking it as having been automatically removed.
The beauty here is if I need to increase the number of concurrent export jobs, I can easily spawn up another JMS client process or tweak the existing processes to run more concurrent MDB handlers without having to touch the web application itself.
I'm curious if there are other alternatives I could be overlooking, concerns I should be considering, or whether this is a solid decoupled solution that has worked for others in the past.
Given your scenario, i would do with session beans.
or there is JMX set up for jobs but they are legacy ways. i dont like jmx.
But just to let you know if these are limited report and needs once per day kind of, and simple form is to use quartz job, But i think you cant run if you can multiple job at same time.
well there are quartz job set up which are rally easy to set up , and you can trigger it from your application, and if you want some clean up , you can create multiple jobs and intelligent you can make them dependent.
you can refer here for quartz set up .
From my understanding of the Heroku platform, they allow only one dyno per app that can handle HTTP requests. Within a Java app, my goal is to have a periodic process run once or twice a day that gets information from Facebook servers and processes it accordingly. If a background worker dyno can't handle web requests, then how should I go about writing a reoccurring process within the web dyno?
In this sense, "handle HTTP requests" refers to the listen side of the connection not the send side. On Heroku, an application can have a single web process* that listens for HTTP connections and many other processes that initiate / send HTTP requests (or connect to other non-HTTP systems).
*Note: You can allocate as many Dynos as you want, to run each process.
To run a process that periodically makes requests to an external service (like Facebook) you can use the Heroku Scheduler Add-on. Then you could either store the results in one of the many relational or NoSQL data-storage add-ons or possibly send the results to other processes via a messaging add-on like CloudAMQP.
If the platform is limiting you, why use it?
There are other platforms that will let you perform this.
You can easily deploy java applications to the cloud using OpenShift and then you use java API with no limitations what soever as far as I know.
OpenShift is also using git, same way Heroku does.
They are both PaaS, so the concept is quite the same, and I think it will be easy for you to try out OpenShift.
And you can also check Google App Engine to see if it has such limitations.
Sorry for not helping you with the specific question, I simply know that at least "one competitor" does not have such a limitation.
Please help me to choose right (stable and safe) approach for my task. I have web application implemented with Spring MVC on Apache Tomcat.
To provide some service I need to make a connection to an external application over network. Also, I have to support specific network protocol with this software.
In this situation my web-app is a client, external application is a server. And also, external application could be run in many instances, so my web-app has to open many sockets.
Each connection should be supported asynchronously, so it seems to I should create a thread for each connection.
I thought I could create a ContextListener for dispatcher servlet of Spring and implement events of life-cycle: init and destroy. So here I could create and start my exotic service on initialization stage and shutdown it on destroy stage.
I realize that my solution might be not accurate enough. May be I should use TaskExecuter or something else. I'd be interested to know what would you advise me.
Thanks a lot!
Since you are already using Spring MVC, it may be easier to simply use Spring's lifecycle callbacks to do the initialization and the cleanup.
You could create a singleton service bean for each external peer (or multiple ones with different configuration settings if they would be identical otherwise) and use them as standard Spring-managed services.
why are you trying make a Service for it? your web application (client) can simply use a Abstract Controller to call/request data from external application and show response on browser, upon any given event...
please be more specific about what you are trying to do