In the most common cases, the BC code is called from a Managed bean (MB) whose execution was originated by an HTTP request made by the web browser. In such cases, there is an active Requestcontext that allows you to use the @Inject
.
The problem is that the job runs on a separate thread, which has no access to a context. To solve this, you must pass the BC to the job and, within the job, create a request context.
The class that creates the job must inject the BC and a Requestcontext; when creating the job, these objects must be passed to the job through a Jobdatamap:
@BusinessController
public class Agendador {
@Inject
private MinhaClasseBC meuObjetoBC;
@Inject
private BoundRequestContext requestContext;
public void agendaJob() throws SchedulerException {
JobDataMap jobData = new JobDataMap();
jobData.put("requestContext", requestContext);
jobData.put("bc", meuObjetoBC);
JobDetail job = newJob(ClasseDoJob.class)
.withIdentity("id", "grupo")
.setJobData(jobData)
.build();
// aqui vem o código da trigger e do agendamento
}
}
The job class then takes these objects and creates the context before calling the BC (and destroys after the call):
public class ClasseDoJob implements Job {
@Override
public void execute(JobExecutionContext jobContext) throws JobExecutionException {
JobDataMap jobData = jobContext.getJobDetail().getJobDataMap();
BoundRequestContext ctx = (BoundRequestContext)jobData.get("requestContext");
MinhaClasseBC bc = (MinhaClasseBC)jobData.get("bc");
ctx.associate(new HashMap<String, Object>());
ctx.activate();
bc.metodoQueFazAlgumaCoisa();
ctx.invalidate();
ctx.deactivate();
}
}
Yeah, my case is EE. I understand that there are trade-offs: you need to have the application URL, and the URL may vary according to the deployment environment (testing, production, etc.); a malicious visitor who discovers the "access port" URL can perform the task more often than desired. Because of that I will keep my answer, but if I need to do something similar in the future I will consider your solution.
– rodrigorgs