Java: How to use Quartz inside a project secured by Apache Shiro

My initial problem was this error message in my eclipse console output:

javax.ejb.EJBException: org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton. This is an invalid application configuration.

My project is to develop a web based application that in some point must update some rows in data base every 24 hours, nothing big or complicated.

So i tried to use quartz, because its very easy to setup, and has a interface that i like to work.

This project uses EJB, and after i get it working I found out that a scheduler was simple as annotation, i think its @Scheduled , but I am not sure. Thanks to my colleage William who knows a lot more about EJB.

The project makes use of java web technologies like JSF 2.2 to view, EJB for control and JPA / Hibernate to data management.

The Apache Shiro was used to implement the security system (Authentication and Authorization) in this application. The problem is that quartz application was not authenticated to use any service in the EJB layer. That why the application is given this error message, no securitymanager accessible.

First i tried the simple way, configuring two text files quartz-config.xml and quartz.conf, and importing the required library to quartz, setting web.xml with the right listener, easy to find with Google. My application was scheduled to run a job, a java class: public class ManutencaoBD extends EJB3InvokerJob ( org.quartz.jobs.ee.ejb.EJB3InvokerJob; ) . Its a little different from the examples, because there you implement a Job (org.quartz.Job) . The EJB3InvokerJob creates hability to run your EJB bean, its very simple.

But the problem persist, if you run your code, the webapp will show error about No SecurityManager.

Solution:

Create a bean capable to start with the application, for JSF 2.2 is simple as putting the right annotation to your bean like this:

@javax.ejb.Singleton
@javax.ejb.Startup
public class QuartzInitialization {

@EJB
private MailingServico mailingServico;

@javax.annotation.PostConstruct
public void postConstruct() {

// Begin - Code to start the security
// My CustomSecurityRealm.class is a class that extends JdbcRealm in
// order to override some querys to database.
DefaultSecurityManager securityManager = new DefaultSecurityManager();
securityManager.setRealm(new CustomSecurityRealm());
SecurityUtils.setSecurityManager(securityManager);
// End - Code to start the security

StdSchedulerFactory factory = new StdSchedulerFactory();
factory.initialize(this.getClass().getResourceAsStream(
"../../../../quartz.properties"));
Scheduler scheduler = factory.getScheduler();
// pass the servlet context to the job
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("servletContext", null);
// define the job and tie it to our job's class
JobDetail job = JobBuilder.newJob(ManutencaoBD.class)
.withIdentity("job1", "group1").usingJobData(jobDataMap).build();
// Trigger the job to run and then repeat every 00:00:00
// "0/5 * * * * ?" De cinco em cinco segundos a partir do 00 segundo
// "0 0 0/12 * * ?" De 12 em 12 horas a partir das 00:00:00
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("job1", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 0 * * ?"))
.build();
// Tell quartz to schedule the job using our trigger
scheduler.scheduleJob(job, trigger);

// New Job to Run Now
JobDetail jobRunNow = JobBuilder.newJob(ManutencaoBD.class)
.withIdentity("triggerRunNow", "group2").usingJobData(jobDataMap)
.build();
Trigger triggerRunNow = TriggerBuilder.newTrigger().startNow()
.withIdentity("triggerRunNow", "group2").build();
scheduler.scheduleJob(jobRunNow, triggerRunNow);

// and start it off
scheduler.start();
}

That solution I had to created the jobs manually, instead of using the quartz-config.xml (Jobs), because the security must be setup before the running job.

There were two jobs, one to run now, and another to run every day at 00:00:00 .

Hope this little code could help you.

Deixe um comentário