I'm building functionality that will enable users to schedule recurring and non-recurring tasks. I need to save these schedules in the database and read active schedules once daily to see if they should be triggered today.
I am using spring/java. I fear if I write this logic myself it will be lacking and not as efficient as it could be.
Required schedule configurations are just like the Outlook calendar, except for being concerned with time. (probably easier to open outlook recurring meeting than read my rendition):
Actual Date
every Nth day, based on start date
every Nth business day, based on start date
every Nth week on one-to-many-selection(Sun,Mon,Tues,etc...), based on start date
the (1st,2nd,3rd,4th,last) (Sun,Mon,Tues,etc...) of every Nth month based on start date
day X of every y months, based on start date
every (jan,feb,mar,apr,etc..) Nth day each year
every (1st,2nd,3rd,4th,last) (Sun,Mon,Tues,etc...) of
(jan,feb,mar,apr,etc..)
What is simple pattern for implementing this? Thanks for any help
Quartz Job Scheduler
What you are looking for can be accomplished easily with the Quartz Job Scheduler Library.
It allows for scheduling of future event, and even with using cron syntax.
Excerpt from project page:
What is Quartz Job Scheduling Library?
Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may execute virtually anything you may program them to do. The Quartz Scheduler includes many enterprise-class features, such as support for JTA transactions and clustering.
Quartz is freely usable, licensed under the Apache 2.0 license.
See Overview.
See example # 3.
Spring
If you do decide to write your own logic and since you are using Spring, you could make use of the some of the functionality provided by Spring (spring-framework-reference)
But I never made use of that, since I face many challenges in getting exactly what I want
QuartzInitializerServlet
Another way would be to make use of the build-in QuartzInitializerServlet. This method is much more flexible in that you can get the scheduler instance and implement your logic from there
A Servlet that can be used to initialize Quartz, if configured as a load-on-startup servlet in a web application.
Using this start-up servlet may be preferred to using the
QuartzInitializerListener in some situations - namely when you want to
initialize more than one scheduler in the same application.
You'll want to add something like this to your WEB-INF/web.xml file:
<servlet>
<servlet-name>
QuartzInitializer
</servlet-name>
<display-name>
Quartz Initializer Servlet
</display-name>
<servlet-class>
org.quartz.ee.servlet.QuartzInitializerServlet
</servlet-class>
<load-on-startup>
1
</load-on-startup>
<init-param>
<param-name>config-file</param-name>
<param-value>/some/path/my_quartz.properties</param-value>
</init-param>
<init-param>
<param-name>shutdown-on-unload</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>wait-on-shutdown</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>start-scheduler-on-load</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
A StdSchedulerFactory instance is stored into the ServletContext. You
can gain access to the factory from a ServletContext instance like
this:
StdSchedulerFactory factory = (StdSchedulerFactory) ctx
.getAttribute(QuartzFactoryServlet.QUARTZ_FACTORY_KEY);
Related
WHAT AM I TRYING TO ACHIEVE
Synopsis:
Trying to create an API or connector for an inhouse monitoring tool that integrates with SCOM [System Center/Microsoft System Operations Manager 2012].
Our tool has a restful page with all the necessary endpoints and simply would like SCOM to read the status of those endpoints.
Thus far according to SCOM documentation and my understanding, I need to build a management pack. And this consists of Authoring tools with visual studio etc.
Whilst I am still going through the documentation on this, whose tackled something like this before. Some guidance on how to approach this would be appreciated.
##### UPDATE [04/01/16] ########
Thinking.... * Plan to create a MP(s) for Discovery, Monitoring and Dashboard.*
New Question...
Created a script using posh that exposes the endpoints needed by SCOM.
+ These need to be converted to a class object (converting posh to xml). - not done yet!
+ Thinking ahead I am not sure what Base Class to use for this discovery script?
A very simple way to do this would be with Web Application Availability Monitoring, which works with any HTTP endpoint. As well as checking availability, this monitor can check the content of the response and raise an alert accordingly.
To get started, use the SCOM console and navigate to Authoring > Management Pack Templates > Create > Web Application Availability Monitoring
This blog is a really good walkthrough of doing that:
http://www.opsmanfan.com/index.php/6-use-scom-2012-to-monitor-a-webapi-without-using-scripts
Some limitations with this approach vs. a custom management pack:
you won't get any control over the alert content (name, desciption etc)
it won't scale well to many monitors (in terms of administrative burden)
you can't represent the health using a complex object model (no classes / discoveries)
If you want to test a large number of URLs with this method, then a community Management Pack called URLGenie might also help:
http://blogs.msdn.com/b/tysonpaul/archive/2015/05/04/urlgenie-management-pack-for-scom-an-easy-solution-for-bulk-website-monitoring.aspx
You are right that custom MP is the right way to do an integration of the custom/third-party monitoring system with SCOM. You have to think about three important things when you are planning your work on such MP:
How you are going to get information from external system
How you are going to persist and use it in SCOM
How you are going to visualize it in SCOM
Let's walk through these three items:
From your intro it looks obvious - your system exposes RESTful API. SCOM (even 2012 or 2016) doesn't have native datasources to parse JSON so you'll need to create custom datasources using Powershell or C# (depends on your experience) . In this case, it might be reasonable to use any standard library to make this job easier.
SCOM has its special object model. You have classes to represent objects, monitors to detect failures/state changes and rules to collect performance metrics and alerts/events. So you'll need to implement Discovery datasources to get data about objects, monitored by your custom monitoring system (such as servers, databases, disks, apps, etc.) and define a class hierarchy to persist these objects in SCOM.
Then you'll need to create datasources for monitors and rules and here you must think before act - what failures, alerts and metrics you want to expose to SCOM. When you have clear understanding of this area - you are good to implement that (again - using PS or C#).
SCOM will give you some OOB visualization after you dome (1) and (2), so in the minimal scenario you'll need to define just a couple of views to show in SCOM console data collected by your MP. In ultimate case - if you want to have some fancy visualization - you'll have to create custom Dashboard. A good option here - use dashboards from SQL Server MP (it was released recently, it's free and it is really cool).
In fact, SCOM is not a monitoring system, but a framework, which has runtime platform, development language, and libraries, so building your own MP is closer to programming than IT administration :)
You also can try to use Silect MP authoring tool, but I'm not sure if it will help you to build custom datasources better than VS.
Good luck!
P.S. feel free to ping me via LinkedIn for more details about MP development.
I am looking for a way to change the steps in the saga, example: insert a step during the processing, preferablly during runtime
Is it possible to do using sagas?
Sagas (particularly those written using Automatonymous) were not designed to handle dynamic configuration at runtime. They are a codified way to create process monitors and workflows.
If you need to dynamically modify the steps of a workflow, you could use the Courier routing slip, which is built into MassTransit. It allows an activity in the workflow to revise the itinerary, adding or removing steps (activities) as needed.
I'd like to control how many threads can be used by a web application.
So far I thought it can be set by creating an application-scope workmanager (Deployments -> [application] -> Configuration -> Workload) and setting the Maximum Thread Constraint.
However recently I have the feeling that it is not true as this workmanager should be referenced from the code so it has to be used explicitly from the application.
What I'd need is to configure that from now on the XYZ application can use max 5 threads but no more. It can be done on global level but I want to control only one application.
As far as I know, if you define the workmanager in app's weblogic.xml or weblogic-application.xml, it's for sure will work on application level instead of config.xml which is domain-level config.
If you create and configurate the workmanager's max-threads-constraint and then reference to it in your app’s web.xml file like this:
<init-param>
<param-name>wl-dispatch-policy</param-name>
<param-value>your_workmanager_name</param-value>
</init-param>
i'm pretty sure, that this constraint will apply only on certain app's level.
I have the feeling that it is not true as this workmanager should be referenced from the code so it has to be used explicitly from the application.
Where'd you find this? I may be wrong but I never heard or read that it should be referenced explicitly from code instead of xml.
For more details take a look on this and this in case you hadn't.
I have a process diagram that directs flow on the basis of threshold variables. For example, for variable x,y; if x<50 I am directed to service task 1 , if y<40 to service task 2, or if x>50 && y>40 to some task..
As intuition tells, I am using compare checks on sequence flow to determine next task.
x,y are input by user but 50, 40 (Let's call these numbers {n}) is a part of process definition(PD).
Now, for a fixed {n} I have deployed a process diagram and it runs successfully.
What should I do if my {n} can vary for different process instances? Is there a way to maintain the same version of process definition but which takes {n} dynamically?
I read about BPMN Model API here. But, I can't seem to figure out how to use it to edit my PD dynamically? Do I need to redeploy it each time on Tomcat or how does it work?
If you change a process model with the model API you have to redeploy it to actually use it. If you want to have a process definition with variable {n} values you can also use a variable for it and set it during the start of the process instance either using the Java API, REST API or the Tasklist.
I'm after some advice on polling an external web service every 30 secs from a Domino server side action.
A quick bit of background...
We track the location of cars thru the TomTom api. We now have a requirement to show this in our web app, overlayed onto a map (google, bing, etc.) and mashed up with other lat long data from our application. Think of it as dispatching calls to taxis and we want to assign those calls to the taxis (...it's not taxis\ calls, but it is similar process). We refresh the dispatch controllers screens quite aggressively, so they can see the status of all the objects and assign to the nearest car. If we trigger the pull of data from the refresh of the users screen, we get into some tricky controlling server side, else we will hit the max allowable requests per minute to the TomTom api.
Originally I was going to schedule an agent to poll the web service, write to a cached object in our app, and the refreshing dispatch controllers screen pulls the data from our cache....great, except, user requirement is our cache must be updated every 30secs. I can create a program doc that runs every 1 min, but still not aggressive enough.
So we are currently left with: our .net guy will create a service that polls TomTom every 30secs, and we retrieve from his service, or I figure out a way to do in Domino. It would be nice to do in Domino database, and not some stand alone java app or .net, to keep as much of the logic as possible in one system (Domino).
We use backing beans heavily in our system. I will be testing this later today I hope, but would this seem like a sensible route to go down..?:
Spawning threads in a JSF managed bean for scheduled tasks using a timer
...or are their limitations I am not aware of, has anyone tackled this before in Domino or have any comments?
Thanks in advance,
Nick
Check out DOTS (Domino OSGi Tasklet Service): http://www.openntf.org/internal/home.nsf/project.xsp?action=openDocument&name=OSGI%20Tasklet%20Service%20for%20IBM%20Lotus%20Domino
It allows you to define background Java tasks on a Domino server that have all the advantages of agents (can be scheduled or triggered) with none of the performance or maintenance issues.
If you cache the data in a bean (application or session scoped). Have a date object that contains the last refreshed date. When the data is requested, check last cached date against current time. If it's more than/equal to 30 seconds, refresh data.
A way of doing it would be to write a managed bean which is created in the application scope ( aka there can only be one..). In this managed bean you take care of the 30sec polling of the webservice by good old java webservice implementation and a java thread which you start at the creation of your managed-bean something like
public class ServicePoller{
private static myThread = null;
public ServicePoller(){
if(myThread == null){
myThread = new ServicePollThread();
(new Thread(myThread)).start());
}
}
}
class ServicePollThread implements Runnable(){
private hashMap yourcache = null;
public ServicePollThread(){
}
public void run(){
while(running){
doPoll();
Thread.sleep(4000);
}
}
....
}
This managed bean will then poll every 30 seconds the webservice and save it's findings in a hashmap or some other managed-bean classes. This way you dont need to run an agent or something like that and you achieve when you use the dispatch screen to retrieve data from the cache.
Another option would be to write an servlet ( that would be possible with the extlib but I cant find the information right now ) which does the threading and reading the service for you. Then in your database you should be able to read the cache of the servlet and use it wherever you need.
As Tim said DOTS or as jjtbsomhorst said a thread or an Eclipse job.
I've created a video describing DOTS: http://www.youtube.com/watch?v=CRuGeKkddVI&list=UUtMIOCuOQtR4w5xoTT4-uDw&index=4&feature=plcp
Next Monday I'll publish a sample how to do threads and Eclipse jobs. Here is a preview video: http://www.youtube.com/watch?v=uYgCfp1Bw8Q&list=UUtMIOCuOQtR4w5xoTT4-uDw&index=1&feature=plcp