How Can jBilling Help You?
Who’s Using jBilling?

“The support we get from jBilling is excellent.”
Ingram Leedy
Elephant Outlook
See all testimonials >

DONE - Replace OS cron by EJB Timer.

Current functionality:
There are a series of processes that have to run periodically. The most important of them is the billing process itself (the process that generates invoices), but there are many more. To do this, you need to setup a cron or other operating system (OS) managed way to call a trigger class in jbilling. This has to be done as part of the installation process and it is OS specific.

Desired functionality:
Provide build-it triggering capabilities to be configured directly in the jbilling.properties file, this way avoid any OS specific configuration.

Technical overview:
EJB provides a timer service since 2.1 (this was not implemented in JBoss when the first version of jbilling when in production). Let's take advantage of this services and let the application server take care of triggering the periodic processes.
See chapter 14 of the free PDF book 'Mastering EJB'. You can download it at www.theserverside.com.

Server tier modifications:
The class to be called is now com.sapienter.jbilling.tools.Trigger. Take a look to it. It is meant to be a standalone client program that will be calling a series of remote methods. Depending on the parameters it will run one or many processes.
So the first thing to do is to convert this class into a session bean that implements TimedObject. This means including all the xdoclet tags in the file to get the interfaces and xml entries done during the build. The 'business logic' of this class will be to setup the timer using the properties from jbilling.properties by calling TimerService.createTimer. Then the actual call to the services (now in the main method of th class) will be in ejbTimeout.

By looking at the Trigger class, you can see that there are many services being called: the first one is the billing process, followed by the ageing process and so on until the credit card expiration emails. We want the billing process to potentially be configured to run many times in a day, while all the rest of the services to run just once per day.

The following new properties will be added to jbilling.properties:
process.time=YYYYMMDD-HHmm (a full date followed by HH is the hours in 24hs format and mm the minutes).
process.frequency=X (where X is an integer >= 0 and < 1440

The fist property indicates at what time of the day the trigger has to happen for the very first time. After this first run you will need X minutes (specified by 'process.frequency') to run the trigger again. Since only the billing process can run more than once per day, we need some logic in the ejbTimout method to verify if the call is the first one of the day (where it runs all the services) or not (where it runs only the billing process).

The first property is optional. If it is not present, or its value is null, then the next trigger will happen at startup + minutes indicated in 'process.frequency'.

Client tier modifications:
Now that we have a timer bean than can periodically run the routine processes, we just need a way to kick off the whole process by invoking this session bean only once when the application server starts up. The way to do this is with a new servlet whose only purpose in life is to run once when the app server is starting and create the session bean for the trigger. You can do this by using the tag 'load-on-startup' when you declare the servlet in the web.xml file.

Database tier modifications:
N/A

Changes mostly to be done in these files:
jbilling.properties
Trigger.java
web.xml
new servlet class for application initialization

The feature is now completed. This is the change log

 
justinli wrote 5 years 22 weeks ago

Questions on this subject

Hi Emil,

After several days studying, I have an overview on this enhancement. But before I start it, I found that it looks like JBoss we bundled does not support the EJB time service. So, what do you think about this? Using Quartz?

Another question is, after the server startup, no more scheduled things can be added? If user/admin changed jbilling.properties to add another scheduled task, he has to restart the server. Is this right?

Best regards,
---------
Justin

---------
Justin

econde wrote 5 years 22 weeks ago

Hi Justin,

Hi Justin,

Yes, you are correct. We will be using Quartz instead of EJB Timers since JBoss doesn't support timers in 3.2.x. You can see that this was the conclusion when we discussed this with Yang some time ago.

For your second question, you are right again. The user will have to restart the server if any of the values in jbilling.properties changes.

Cheers,

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

 
justinli wrote 5 years 22 weeks ago

Jobs type

Hi Emil,

It's great having been right twice. lol

Here is another question. We have 8 kinds of jobs, billing process, ageing process and so on. And we only have one pair of properties in the jbilling.properties, process.time and process.frequency. What's the hidden rules to trigger process ageing and others. Or, there should be another seven keys in jbilling.properties, like ageing.process.time, ageing.process.frequency.

At the same time, Here is the last one. Should some log lines be printed in some log files? And how?

Thanks,
--Justin

---------
Justin

econde wrote 5 years 21 weeks ago

Justin,

Justin,

I've just copied two paragraphs from the task description:

"The fist property indicates at what time of the day the trigger has to happen for the very first time. After this first run you will need X minutes (specified by 'process.frequency') to run the trigger again. Since only the billing process can run more than once per day, we need some logic in the ejbTimout method to verify if the call is the first one of the day (where it runs all the services) or not (where it runs only the billing process).

The first property is optional. If it is not present, or its value is null, then the next trigger will happen at startup + minutes indicated in 'process.frequency'."

So the answer to your question is, there is only one set of properties. The billing process can run more than once per day, the remaining 7 services will run no more than once per day.

As far a logging goes, it is a good practice to log, specially for a feature like this. You can find example of logging all over the jbilling code. We use log4j for logging, it usage is super simple:

Logger log = Logger.getLogger(theNameOfYourClass.class);
log.debug("something to log");

You might want to use some 'info' level for important messages, while some 'debug' level for the rest.

Cheers,

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

 
justinli wrote 5 years 21 weeks ago

Steps to do it

Okay, Thanks Emil.

The following are steps for this enhancement, please double check.
1. Put quartz.jar to jbilling/lib . I suppose that the path is included in the application search path. And the quartz 1.4.5 is used.

2. Introduce new class TriggerSessionBean into package com.sapientar.jbilling.tools. Inside method ejbCreate, the Trigger is initialized. I don't think this package is good. What do you think? Which package should we put the class in?
Modify web.xml to load TriggerSessionBean when the server starts.

3. Modify Trigger to implement quartz Job, and add a method execute inside which, real function will be done. At first time the job is kicked each day, everything will be run, otherwise, only billing process will run.

4. Add a method initialized to Trigger, which load configuration from jbilling.properties and initialize quartz.

That's all and Thanks

--Justin

---------
Justin

econde wrote 5 years 21 weeks ago

Looking good, Justin. My

Looking good, Justin. My comments:

1- The jar file should be in jbilling\server\jbilling\lib
2- You're right, that package is not good. How about com.sapienter.jbilling.server.process ? There's classes related to the billing process and ageing already there. Now, you don't need to use/create the method 'ejbCreate'. We are not using EJB timers and that method is required by the EJB specification. Since we are using Quartz now, you can come up with a better name.
3- All good.
4- All good as well.

Cheers,

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

 
justinli wrote 5 years 21 weeks ago

Thanks and Timeframe

Timeframe for this taks is three weeks. Half for coding and half for testing.

This is not a big one. But I'm new, so I rather choose longer timeframe.

Best regards,
--Justin

---------
Justin

econde wrote 5 years 21 weeks ago

Thanks for the update

Thanks for the update Justin. Please keep us posted on your progress and do not hesitate to ask any questions ;)

Cheers,

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

 
justinli wrote 5 years 20 weeks ago

Loading jbilling.properties

Hi Emil,

How can I load jbilling.properties? I'm wondering if there are some global thing which I can used to read the config file, or I load it myself?

Thanks,
--Justin

---------
Justin

econde wrote 5 years 20 weeks ago

To read jbilling.properties

To read jbilling.properties user the class com.sapienter.jbilling.common.SystemProperties

There is also a helper static method at com.sapienter.jbilling.common.Util.getSysProp(String key)

Cheers,

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

 
justinli wrote 5 years 20 weeks ago

Thanks and one more question

Hi Emil,

I have one more question about Trigger initialization error handling. What if the format is not correct or frequency value absent? Throw an exception and interrup startup (I don't think we can do this.) Or just give a log line to tell this.
I suggest print out something on console.

What do you think?

Thanks,
--Justin

---------
Justin

econde wrote 5 years 20 weeks ago

Hi Justing,

Hi Justin,

I've re-posted a previous answer (to a Yang's question), with some extra comments:

Q: process.frequency=0? Does that mean disable the recursive trigger?
A: when this value is 0, let's assume the 0hs of next day. This is to simplify the setup, otherwise every time the server is restarted, they will have to change this parameter. So for example if process.time is not present, and process.frequency is 0, then the next run will happen the next day at 0hs and from then on every 24 hs. This means that we are going to try to run the trigger at least once per day.

Q: Does process.frequency only affect the billing process? It seems other process (aging, and etc) will execute once and only once per day. So the frequency for those process will be 24h.
A: yes, it only affects the billing process, the rest only run once per day as you mentioned.

Q: Shall we add some constraints for "process.time"? For example, if user point to a time like "2010-1-1", then it will be not point. And if a user point to a time earlier than the start-up time, what we should do
A: I'd say to validate the date, and if it is incorrect, then post an error in the log and do not start the trigger timer. By incorrect I mean an invalid date (2005-15-15), or a date in the past (2005-10-10), but not in the future. If the date is 2010-1-1 it is fine, odd by still fine (you could log a warning in this case).

In any case, I agree with you Justin. We should not stop jbilling from starting up. In the worst case, when the properties are just wrong, we log and leave the trigger out of the timer.

Cheers,

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

 
justinli wrote 5 years 19 weeks ago

Another question

I put Trigger to tools package. And I guess that package is not in server package. So when startup, ClassNotFound exception comes out. I move it to process package now. Which package should I put it in?

--Justin

---------
Justin

econde wrote 5 years 18 weeks ago

Justin, this class should be

Justin, this class should be in the package com.sapienter.jbilling.server.process . You should not have any problems with the class there.

Thanks for the update, looking good.
Cheers,

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

 
justinli wrote 5 years 18 weeks ago

How can I commit source code?

Hi Emil,

I think I finish it. I tested the feature by log at now, for I still can not understand the whole application.

Is that okay? If yes, How can I upload my changes?

--Justin

---------
Justin

econde wrote 5 years 18 weeks ago

Justin,

Justin,

It's up to you how you want to proceed. You can ask me more questions on the parts you do not understand, or you can send me the files and I can comment on what is that is missing if you want. I can also take it from here.

You can create an SVN patch or Zip the files you've changes and send and email with the attachment to the mailing list. You will have to change the name of the zip file from .zip to .jar because the list does not allow zip attachments.

Cheers,

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

 
justinli wrote 5 years 18 weeks ago

I sent it out. Did you get

I sent it out. Did you get the email? I think I got even though there is an warning from gmail.

BTW, I sent a tar-gzip file.

--Justin

---------
Justin

econde wrote 5 years 17 weeks ago

Hi Justin,

Hi Justin,

I've got the email with the file, thanks!. I need you to send the contributors fax before I can take a look to your code. See point 5 of the guide http://www.jbilling.com/?q=node/21&pl=gi for details.

Cheers,

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

 
justinli wrote 5 years 17 weeks ago

Hi Emil,I'm afraid I havn't

Hi Emil,

I'm afraid I havn't got a fax. Looks like I have to send the CLA out by snail mail.

Sorry for that.

--Justin

---------
Justin

econde wrote 5 years 17 weeks ago

Snail mail is fine Justin. I

Snail mail is fine Justin. I look forward to see the stamps :)
In the meantime, I'll go ahead and review the code. This feature is very important and will be included in the upcoming release (1.0.4).

Cheers,

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

 
justinli wrote 5 years 17 weeks ago

All right and Thanks.I will

All right and Thanks.

I will pick some pretty stamps, ;).

Any questions let me know when you reviewing the code.

Cheers,
--Justin

---------
Justin

 
justinli wrote 5 years 18 weeks ago

OKAY, I like to send a zip

OKAY, I like to send a zip file to the mailing list.

Day after day, I will know the whole system. Of coz, I will ask you many questions. And for this job, I think it's fine because this enhancement need not much knowledge of whole application.

--Justin

---------
Justin

 
justinli wrote 5 years 19 weeks ago

Sorry for late reply and my point

From my point, I think the date is past, like 2005-10-10 is okay. We start from 2005-10-10 plus enough time mintues indicated frequency. Quartz has this functionality. Then user need not modify the properties file at every startup.

And my status: Code complete and testing.
I have some trouble on deployment and setup jboss. I think it's fine. I need some time to get be familiar with Jboss, and the development enviorment.

--Justin

---------
Justin

 
yangsun wrote 5 years 39 weeks ago

I need some further

I need some further clarifications on this feature.

1. process.frequency=0? Does that mean disable the recursive trigger?

2. Does process.frequency only affect the billing process? It seems other process (aging, and etc) will execute once and only once per day. So the frequency for those process will be 24h.

3. Shall we add some constraints for "process.time"? For example, if user point to a time like "2010-1-1", then it will be not point. And if a user point to a time earlier than the startup time, what we should do?

Thanks
Yang Sun

econde wrote 5 years 39 weeks ago

Interesting. Let's see:

Interesting. Let's see:

1) when this value is 0, let's assume the 0hs of next day. This is to simplify the setup, otherwise every time the server is restarted, they will have to change this parameter. So for example if process.time is not present, and process.frequency is 0, then the next run will happen the next day at 0hs and from then on every 24 hs. This means that we are not giving any way to disable the trigger: it will run at least once per day.
2) yes, it only affects the billing process, the rest only run once per day as you mentioned.
3)I'd say to validate the date, and if it is incorrect, then post an error in the log and do not start the trigger timer. By incorrect I mean an invalid date (2005-15-15), or a date in the past (2005-10-10), but not in the future. If the date is 2010-1-1 it is fine, odd by still fine (you could log a warning in this case).

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

 
yangsun wrote 5 years 40 weeks ago

Does the bundled JBoss support EJB 2.1?

Hi, Emil:

I got the ideas on how to modify this code. Now I have two problems.

1. Does the bundled JBoss support EJB 2.1?
TimedObject and other timer related classes are in the javax.ejb naming space. But I search the jboss-j2ee.jar, I cannot find those classes.

2. Could you provide the script which will call the Trigger class(use At or Cron utility)? Then I can have more information on the logic of trigger different services.

Another thinking is to use "ServletContextListeneer" to trigger the create timer operations. I think it is another elegant way to create the timer at the application startup.

Regards,
Yang Sun

econde wrote 5 years 40 weeks ago

Yang, the people from JBoss

Yang, the people from JBoss answered and it is only since 4.0 that they support EJB Timers, so let's go then with Quartz.

Cheers,

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

econde wrote 5 years 40 weeks ago

1) I hope it does. We are in

1) I hope it does. We are in JBoss 3.2.6, I have posted a question in the JBoss forums about this (I searched, but could not find a concrete answer). Migrating to JBoss 4 is quite difficult because of the changes in webservice. I tried hard about a year ago and it really wasn't ready for production. So let's wait for some answer from JBoss. If they do not support it, we can use Quartz (www.opensymphony.com/quartz), which is actually much better than J2EE Timers, but it would be adding yet another component to jbilling package.

2) There is not too much of a script, it is just a call to the trigger class Trigger. So to call this class from the command line looks like this:

java com.sapienter.jbilling.tools.Trigger

You can also give some parameters. To run it for today, skipping the billing process:

java com.sapienter.jbilling.tools.Trigger 2006-04-27 2

About your suggestion on ServletContextListener, feel free to implement this startup in what you think is the most elegant way. I made an initial suggestion, but there are always better way to do the same thing :)

Cheers,

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

 
yangsun wrote 5 years 40 weeks ago

Thanks for your answers.

Thanks for your answers. Let's wait for their reply.

I know we are using something like "java com.sapienter.jbilling.tools.Trigger 2006-04-27 2" to trigger the command execution. But I want to find where our program call this kind of command. So I will know the current logic for trigger the timed event and make sure the new code will not break the existing logic. Sorry for my poor English...

Regards,
Yang Sun

econde wrote 5 years 40 weeks ago

Yang, there is no code to

Yang, there is no code to call the trigger class. In UNIX it'd be a cron and in windows an AT command. So the chain is:
1 - The OS triggers the call (using cron or at) to the Trigger class
2 - The trigger class calls the many jbilling services, like the billing process, ageing, etc...

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

 
yangsun wrote 5 years 40 weeks ago

Thanks. But in the

Thanks. But in the installing process, I cannot remember that I have set up anything related to AT on my windows machine. Did I lost some steps in the full setup steps?

econde wrote 5 years 40 weeks ago

That is a good point Yang.

That is a good point Yang. You did not do that installation step because the installation instructions are not complete. :(. I thought that instead of fixing the instructions, might as well fix jbilling so we do not need to set-up an 'AT' command as part of the installation. The information of when to run the trigger and how often is then moved from the AT command to the file jbilling.properties.
Sorry for the confusion! Imagine if you are confused, how much a normal user would be? That's why this task is very important.

Cheers,

Emiliano Conde
Lead Developer - jbilling

Emiliano Conde
Lead Developer - jBilling

Please register or login to post a comment.