Calling a method in application-scoped bean from quartz job - jsf

I have an application scoped bean
#ManagedBean(name = "myController")
#ApplicationScoped
public class MyController implements Serializable{
...
public void allOn(){...}
And i want to call the allOn() method from a quartz-job
import org.quartz.Job;
public class CronJobAllOn implements Job{
#Override
public void execute(..){
//call allOn();}
}
I tried to pass the FacesContext to the Job-Class via the JobDataMap
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("facesContext", FacesContext.getCurrentInstance());
JobDetail job = newJob(CronJobAllOn.class)
.usingJobData(jobDataMap)
.withIdentity("job1", "group1")
.build();
But it only throws an IllegalStateException when i try to call it in the CronJobAllOn Class
public void execute(JobExecutionContext context) throws JobExecutionException {
FacesContext fc= (FacesContext) context.getMergedJobDataMap().get("facesContext");
MyController test = (MyController)fc.getExternalContext().getApplicationMap().get("MyController");
test.allOn();}
How can i call the allOn() method in MyController from a quartz-job?

I got the solution for my Problem, the short comment from BalusC put me on the right path.
I switched to TomEE, to get CDI.
To use the CDI-Bean injection in my jobs, i had to create my own JobFactory Class:
public class CdiJobFactory implements JobFactory {
#Inject
#Any
private Instance<Job> jobs;
#Override
public Job newJob(TriggerFiredBundle triggerFiredBundle, Scheduler scheduler) throws SchedulerException {
final JobDetail jobDetail = triggerFiredBundle.getJobDetail();
final Class<? extends Job> jobClass = jobDetail.getJobClass();
for (Job job : jobs) {
if (job.getClass().isAssignableFrom(jobClass)) {
return job;
}
}
throw new RuntimeException("Cannot create a Job of type " + jobClass);
}
create the Factory
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.setJobFactory(cdiJobFactory);
after that i was able to inject myController:
public class CronJobAllOn implements Job{
#Inject
private MyController mc;
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
mc.allOn();
}

Related

I can't use mockito to replace the method call in SpringBatch

I'm trying to use mockito to replace the method call in SpringBatch. The code is greatly simplified and removed unnecessary to reduce it, if something is missing, write, I will add.
Spring Batch Settings File
#Configuration
#EnableBatchProcessing
public class ListBatchConfig {
#Bean
public Job jobListBath(JobBuilderFactory jobBuilderFactory,
StepBuilderFactory stepBuilderFactory,
ItemReader<Student> itemReaderListBath,
ItemProcessor<Student, Marksheet> processorListBath,
ItemWriter<Marksheet> itemWriterListBath
) {
Step step = stepBuilderFactory.get("List-load")
.<Student, Marksheet>chunk(3)
.reader(itemReaderListBath)
.processor(processorListBath)
.writer(itemWriterListBath)
.build();
return jobBuilderFactory.get("L-Load")
.incrementer(new RunIdIncrementer())
.start(step)
.build();
}
#Bean
public ItemReader<Emaill> itemReaderListBath() {
return new ListItemReader();
}
...
The ItemReader is described in a separate class List Item Reader
#Component
#Slf4j
public class ListItemReader implements ItemReader<Student> {
#Autowired
private CalService calService ;
DataAtributes dataAtributes;
...
#Override
public Student read() {
//Тут вызывается метод сервиса, который необходимо подменить
dataAtributes = new DataAtributes(1,"test");
Integer val = calService.addAttr(dataAtributes);
...
}
Here is the service itself
#Service
public class CalService {
public int addI(int input1) {
return 0;
}
public Integer addAttr(DataAtributes attr) {
return 0;
}
}
in this service, the Job starts
#Service
public class StartJob {
#Autowired
JobLauncher jobLauncher;
#Autowired
Job jobDeveloper;
public void launchJob() throws Exception {
...
JobExecution jobExecution = jobLauncher.run(jobDeveloper, params);
and the testing class itself
#SpringBootTest
public class CaclServisTest {
#Mock
CalService calcService;
#InjectMocks
StartJob
#Autowired
StartJob startJob;
#Test
void add() {
DataAtributes dataAtributes = new DataAtributes(1,"test");
when(calcService.addAttr(dataAtributes)).thenReturn(57);
startJob.launchJob();
}
}
As a result, the native method is called, not the substituted one.
I do not understand what service should be installed #InjectMocks
Your #Mock field is not available for in Spring context.
In particular: #Autowire StartJob startJob uses CalService from Spring context, not your mock.
To replace a bean in Spring context, use #MockBean instead:
#SpringBootTest
public class CaclServisTest {
#MockBean
CalService calcService;
#Autowired
StartJob startJob;
#Test
void add() {
DataAtributes dataAtributes = new DataAtributes(1,"test");
when(calcService.addAttr(dataAtributes)).thenReturn(57);
startJob.launchJob();
}
}

Why is my Primefaces.current() returning null

So, I have this page:
#Named("ManagementPage")
#ViewScoped
#Getter
#Setter
#Join(path = "/{appScope}/admin/management",
to = "/pages/scoped/managementOverview.xhtml")
#Page(
group = "kitchen",
icon = "mdi mdi-comment-text",
key = "management",
navigation = Page.Navigation.ADMIN_SCOPED,
outcome = "/pages/scoped/managementOverview.xhtml",
auth = #PageAuth(value = "MANAGER_ACCESS", scoped = true))
public class ManagementPage implements Serializable {
private static final long serialVersionUID = 1L;
#Inject
private ManagementModel model;
#PostConstruct
public void init() {
this.model.init();
}
}
It's ViewScoped. And the model for it is:
#Log4j
#Dependent
#Getter
#Setter
public class ManagementModel implements Serializable {
...
}
I want, whenever I receive an event, to refresh some UI on the frontend (I'm using JSF). For that, I've created this dispatcher:
#ApplicationScoped
public class OrderEventDispatcher {
private static final List<ManagementModel> subscriptions = new ArrayList<>();
public static void addSubscriber(ManagementModel subscriber) {
subscriptions.add(subscriber);
}
public static void removeSubscriber(ManagementModel subscriber) {
subscriptions.remove(subscriber);
}
public void observerOrderCreated(#Observes FrontendEvent frontendEvent) {
if(frontendEvent instanceof ContentItemCreatedEvent){
if(!"order".equals(((ContentItemCreatedEvent) frontendEvent).getTypeKey())){
return;
}
}
if(frontendEvent instanceof ContentItemChangedEvent){
if(!"order".equals(((ContentItemChangedEvent) frontendEvent).getTypeKey())){
return;
}
}
subscriptions.forEach(ManagementModel::orderInit);
}
}
(I have implemented a proper equals for this in my model)
For my dispatcher to work, I'm subcribing with my model to it (the methods are inside the model)
#PostConstruct
public void init() {
id = totalIds++;
OrderEventDispatcher.addSubscriber(this);
...
And then i unsubscribe before I destroy the model:
#PreDestroy
public void preDestroy() {
OrderEventDispatcher.removeSubscriber(this);
}
And finally, the methods I call from my dispatcher:
public void orderInit() {
loadMergedOrders();
initializeDonut();
PrimeFaces.current().executeScript("orderInit()");
}
I'm doing all this in order to refresh my page (even when multiple instance of the same page are open) in reaction to an event (some item is created/deleted/modified, of that the FrontendEvent takes care). Now the issue is that my PrimeFaces.current() is always returning null, I've added a breakpoint in the init() method and I tried using PrimeFaces.current() and it worked then, but then when I went through the Dispatcher and into the orderInit() with the debugger I've seen that PrimeFaces.current() now returns null. Does anyone have any idea what I'm doing wrong? If not how to fix this then maybe a different approach to solving this. Thanks for your time!

Application scoped managed bean not initializing

I have an application scoped managed bean which I am trying to inject into a session filter to filter rules based on the map provided from application scoped bean .
The Application scoped beans purpose was to load application configuration from the database into the Map which can be accessed during the scope of the application.
#Named
#ApplicationScoped
public class ApplicationConfig implements Serializable {
private Map<String,String> accessRule;
private static final long serialVersionUID = -7984677603595580195L;
#PostConstruct
public void init() throws SQLException, Exception {
System.out.println("ApplicationContainer INIT");
accessRule.put("A", "A");
}
public Map<String,String> getAccessRule() {
return accessRule;
}
public void setAccessRule(Map<String,String> accessRule) {
this.accessRule = accessRule;
}
}
I have tried #PostConstruct and also tried using the constructor too but the bean is not being called.This how the Named bean is being injected
#WebFilter(urlPatterns = { "/*" })
public class ApplicationFilter implements Filter {
private static final String FACES_RESOURCES = "javax.faces.resource";
private static final Logger log = Logger.getLogger(ApplicationFilter.class.getName());
private boolean disableFilter;
private String errorPage;
private String indexPage;
#Inject
public ApplicationConfig applicationConfig;
private List<String> ignoredResources = new ArrayList<>();
#Override
public void destroy() {
// TODO Auto-generated method stub
}
#Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
System.out.println(applicationConfig.getAccessRule());
arg2.doFilter(arg0, arg1);
}
#Override
public void init(FilterConfig arg0) throws ServletException {
}
}
I have used #Named / #Inject and still doesn't work. I want to use a application scoped bean that takes details from DB and used it in a WebFilter. Kindly help

How to set jsf locale in junit test?

i have a junit test method that calls a backing bean method as follows:
myBackingBean.signup();
, in the backing bean method there's a call to Faces.getLocale() and it gives null pointer exception in the line
UIViewRoot viewRoot = context.getViewRoot();
please advise how to be able to set locale in test method and fix this error.
solution was as follows:
1- add the following class to project:
public abstract class FacesContextMocker extends FacesContext {
private FacesContextMocker() {
}
private static final Release RELEASE = new Release();
private static class Release implements Answer<Void> {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
setCurrentInstance(null);
return null;
}
}
public static FacesContext mockFacesContext() {
FacesContext context = Mockito.mock(FacesContext.class);
setCurrentInstance(context);
Mockito.doAnswer(RELEASE).when(context).release();
return context;
}
}
2- In #Before for the test use the following code:
FacesContext facesContext = FacesContextMocker.mockFacesContext();
UIViewRoot uiViewRoot = Mockito.mock(UIViewRoot.class);
Mockito.when(facesContext.getCurrentInstance().getViewRoot())
.thenReturn(uiViewRoot);
Mockito.when(
facesContext.getCurrentInstance().getViewRoot().getLocale())
.thenReturn(new Locale("en"));

CDI not working when Injecting in Generics class - Java

I'm having problems with CDI on tomcat. That's some relevant part of my code:
public class JPAUtil {
private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("unit");
#Produces #RequestScoped
public static EntityManager getEntityManager() {
return emf.createEntityManager();
}
public void close(#Disposes EntityManager em) {
em.close();
}
}
My DAO Class:
public class DAO<T> implements Serializable{
private final Class<T> classe;
#Inject
protected EntityManager em;
public DAO(Class<T> classe) {
this.classe = classe;
}
}
and a child class:
public class UserDao extends DAO<User> implements Serializable{
public UserDao() {
super(User.class);
}
}
Because of the Generics, I used a producer for the DAO class:
public class DAOFactory {
#Produces
#SuppressWarnings({ "rawtypes", "unchecked" })
public DAO createDAO(InjectionPoint injectionPoint) {
ParameterizedType type = (ParameterizedType) injectionPoint.getType();
Class classe = (Class) type.getActualTypeArguments()[0];
return new DAO(classe);
}
}
In this example:
public class Test {
#Inject UserDAO userDAO;
#Inject DAO<User> dao;
}
When I try to use the UserDAO class, everything works fine, but when I use the DAO, the EntityManager remains null. Anyone have any idea?
In DAOFactory you instantiate the DAO with new operator, if you do so, CDI has no chance to inject dependencies in the DAO instance.
While in UserDAO CDI manages the entity manager injection.
So in DAOFactory you should set manually the entity manager in the newly created DAO instance.

Resources