Why is my EntityManager null in my Quartz Job on Wildfly 10? - quartz-scheduler

I'm trying to implement a batch upload job in my app running on Wildfly 10. I want to create a Quartz job that will download some files and load them in the database. However when my job runs the entitymanager is always null. How can I get my entity manger injected in this case? I wrote the following code that simplifies my situation as much as possible. Can anyone tell me where I've gone wrong?
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
#Stateless
public class DownloadService implements Job {
#PersistenceContext
private EntityManager entityManager;
#Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
if (entityManager == null) {
System.out.println("############## entityManager is null ####");
} else
System.out.println("************** WORKING ***************");
}
}

Have you scanned this class using <context:component-scan base-package="your.package"/>.

Related

Why does JobBuilder says could not autowire?

I am following this Udemy course(Batch Processing with Spring Batch & Spring Boot
) for Spring Batch. In the course JBF(JobBuilderFactory) is depracated so I googled what to use instead and it says use JobBuilder.
Right now jobBuilder and stepBuilder are underlined red and says could not autowired.
package com.example.springbatch;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
//1st step
#EnableBatchProcessing
//2nd //use of this?
#ComponentScan("com.example.config") //job and steps will go in this packet
public class SpringBatchApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBatchApplication.class, args);
}
}
package com.example.config;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration //add annot
public class SampleJob { //3rd creating first samp job
//5th Create the job, spring batch provides one class - job builder. And create the obj named jobBuilder
#Autowired
private JobBuilder jobBuilder;
#Autowired
private StepBuilder stepBuilder;
#Bean //4th define #Bean for the first job
public Job firstJob() { //Job(interface) imports core.Job
//6th use
return jobBuilder.get("First Job") //use get First Job is 1st job name
.start(firstStep()) //Inside the start, pass in your step. Job can hava single or multiple step
.build();
}
#Bean //7th Adding the Step interface. Autowire it as well.
Step firstStep() {
return stepBuilder.get("First Step")
.tasklet(firstTask()) //Will need to call Tasklet.
.build(); //call build to create the step.
}
//8th
private Tasklet firstTask() {
return new Tasklet() {
#Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
System.out.println("This is first tasklet step");
return RepeatStatus.FINISHED; //need this
}
};
}
}
I tried to search on google and this is suppose to print System.out.println("This is first tasklet step");
The course is probably using Spring Batch 4. In Spring Batch 5, those builder factories were deprecated for removal and are not exposed as beans in the application context by the #EnableBatchProcessing annotation. Here is the relevant section in the migration guide about that: JobBuilderFactory and StepBuilderFactory bean exposure/configuration.
The typical migration path from v4 to v5 in that regard is as follows:
// Sample with v4
#Configuration
#EnableBatchProcessing
public class MyJobConfig {
#Autowired
private JobBuilderFactory jobBuilderFactory;
#Bean
public Job myJob(Step step) {
return this.jobBuilderFactory.get("myJob")
.start(step)
.build();
}
}
// Sample with v5
#Configuration
#EnableBatchProcessing
public class MyJobConfig {
#Bean
public Job myJob(JobRepository jobRepository, Step step) {
return new JobBuilder("myJob", jobRepository)
.start(step)
.build();
}
}

Injection of #PersistenceContext in CDI-Unit

Here is the unit testing code. When we run unit test code (SampleServiceTest2); EntityManager injected in AbstractDao is always null! How can we inject em during unit test.
*** SampleServiceTest2.java
import javax.inject.Inject;
import org.jglue.cdiunit.CdiRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
#RunWith(CdiRunner.class)
public class SampleServiceTest2 {
#Inject SampleService greeter;
#Test
public void testGreeter() throws Exception {
System.out.println("before2");
greeter.addSampleData(new SampleDataDto(), new KullaniciDto());
System.out.println("after2");
}
}
*** SampleService.java
import javax.ejb.Stateless;
import javax.inject.Inject;
....
#Stateless
#SecuredBean
public class SampleService {
#Inject
SampleLogic sampleLogic;
#Yetki(tag="perm_add_sample_data")
public void addSampleData(SampleDataDto data, KullaniciDto aktifKullaniciDto){
SampleDataHelper sampleDataHelper = new SampleDataHelper();
SampleData sampleData = sampleDataHelper.getEntity(data);
KullaniciHelper kullaniciHelper = new KullaniciHelper();
Kullanici kullanici = kullaniciHelper.getEntity(aktifKullaniciDto);
sampleLogic.addData(sampleData, kullanici);
}
}
**** SampleLogic.java
import javax.inject.Inject;
....
public class SampleLogic {
#Inject
SampleDataDao sampleDataDao;
public void addData(SampleData data, Kullanici kullanici) {
addData1(data,kullanici);
System.out.println("SampleLogic : addData() called!");
}
public void addData1(SampleData data, Kullanici kullanici) {
sampleDataDao.create(data, kullanici);
}
}
**** SampleDataDao.java
public class SampleDataDao extends AbstractDao<SampleData> {
private static final long serialVersionUID = 1L;
}
**** AbstractDao.java
public abstract class AbstractDao<T extends BaseEntity> implements Serializable {
private static final long serialVersionUID = 1L;
#PersistenceContext(unitName="meopdb")
private EntityManager em;
protected EntityManager getEm() {
return em;
}
#SuppressWarnings("rawtypes")
private Class entityClass;
#SuppressWarnings("rawtypes")
private Class getEntityClass() {
if (entityClass == null) {
entityClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
return entityClass;
}
public T create(T t, Kullanici kullanici) {
if (t.getId() != null) {
throw new IllegalStateException("Create Operation: Oid should be null");
}
t.setId(getSeqNextValue(t));
t.setEklemeZamani(new Timestamp(Calendar.getInstance().getTimeInMillis()));
t.setEkleyenKullaniciId(kullanici.getId());
t.setDurumId(EnumDurum.AKTIF.getValue());
t = em.merge(t);
em.flush();
return t;
}
}
If you test with CDIUnit, the only thing you get is CDI injections, not the full power of Java EE. Injecting entityManager using #PersistenceContext into AbstractDAO is not part of standalone CDI, it is only supported when application is running within a Java EE application server.
The solution is to inject EntityManager using CDI mechanism and create a producer. The producer could be then switched for an alternative in unit tests to provide test entityManager. However, setting up JPA in a standalone unit test is not so straightforward, as you need to specify connection properties directly in persistence.xml file. Also, do not forget to add dependencies on a JPA implementation (hibernate, eclipselink) into your test dependencies.
However, if you do not want to adapt your application's code or you need more than CDI in your tests, you should have a look at Arquillian Java EE test framework.
Here is an example for CDIUnit:
public abstract class AbstractDao<T extends BaseEntity> implements Serializable {
...
#Inject
#Named("meopdb")
private EntityManager em;
...
}
// producer in application - just a wraper over `#PersisteneContext`
public class EntityManagerProducer {
#Produces
#PersistenceContext(unitName="meopdb")
#Named("meopdb")
private EntityManager em;
}
/* producer in your test sources - it creates entityManager via API calls instead of injecting via `#PersistenceContext`. Also, a different persistence unit is used so that it does not clash with main persistence unit, which requires datasource from app server
*/
public TestEntityManagerProducer {
#Produces
#ProducesAlternative // CDIUnit annotation to turn this on as an alternative automatically
#Named("meopdb")
public EntityManager getEm() {
return Persistence
.createEntityManagerFactory("meopdb-test")
.createEntityManager();
}
}
And it is not yet enough. You need to create a new persistence.xml in your test resources with the test persistence unit named "meopdb-test". For this unit you need to specify RESOURCE_LOCAL transaction-type, and specify connection information. And last thing not to forget - you need to list all your entities in the persistence.xml, or in external orm file. This is because your tests run outside of application server. Inside app server, JPA can find entities automatically.
As #OndroMih said, in CDI-Unit, the only thing you get is CDI injections. So you have to cheat a little.
You can use extension do add javax.inject.Inject annnotation to all #PersistenceContext injections
import java.util.Set;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.*;
import javax.inject.Inject;
import javax.persistence.PersistenceContext;
import org.apache.deltaspike.core.util.metadata.AnnotationInstanceProvider;
import org.apache.deltaspike.core.util.metadata.builder.AnnotatedTypeBuilder;
public class AddInjectToPersistenceContextInjectionsCdiExtension implements Extension {
<T> void processAnnotatedType(#Observes ProcessAnnotatedType<T> pat) {
Set<AnnotatedField<? super T>> fields = pat.getAnnotatedType().getFields();
for (AnnotatedField<? super T> field : fields) {
if (shouldInjectionAnnotationBeAddedToField(field)) {
AnnotatedType<T> at = pat.getAnnotatedType();
AnnotatedTypeBuilder<T> builder = new AnnotatedTypeBuilder<T>().readFromType(at);
Inject injectAnnotation = AnnotationInstanceProvider.of(Inject.class);
builder.addToField(field, injectAnnotation);
pat.setAnnotatedType(builder.create());
}
}
}
private <X> boolean shouldInjectionAnnotationBeAddedToField(AnnotatedField<? super X> field) {
return !field.isAnnotationPresent(Inject.class) &&
field.isAnnotationPresent(PersistenceContext.class);
}
}
and produce suitable EntityManager in test class
#RunWith(CdiRunner.class)
#AdditionalClasses(AddInjectToPersistenceContextInjectionsCdiExtension.class)
public class SampleServiceTest2 {
#Inject SampleService greeter;
EntityManagerFactory emf;
#PostConstruct
void init() {
emf = Persistence.createEntityManagerFactory("integration");
}
#Produces
EntityManager createEntityManager() {
return emf.createEntityManager();
}
#Test
public void testGreeter() throws Exception {
}
}
It's not exactly equivalent of what Java EE container does, but it's close enough more often than not.

Eclipselink Performance on Wildfly

I've eclipselink v 2.5 enabled application running on Wildfly 8.1 the problem I've noticed is the memory increasing after starting the application because there are huge number of instances of the following classes (snapshot of Visaul VM):
org.eclipse.persistence.internal.identitymaps.HardCacheWeakIdentityMap$ReferenceCacheKey 13083824 13,083,824 (3.1%) 125,806 (1.4%)
org.eclipse.persistence.internal.helper.linkedlist.LinkedNode 3020376 3,020,376 (0.6%) 125,849 (1.1%)
org.eclipse.persistence.indirection.IndirectList 916608 916,608 (0.3%) 14,322 (0.2%)
When I manually start GC no change happen for these classes and it continue to increase the total number of instances.
here is an EJB as a sample from my code which shows the way I'm using to access the persistence context:
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import com.sh.entities.Groups;
#Stateless
public class GroupsFacade extends AbstractFacade<Groups> {
#PersistenceContext(unitName = "WebApplication3PU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public GroupsFacade() {
super(Groups.class);
}
public Groups getByGroupName(String name) {
TypedQuery<Groups> query = getEntityManager().createNamedQuery("Groups.findByGroupName", Groups.class);
query.setParameter("groupName", name);
return query.getSingleResult();
}
Do any one know where is the problem and why this happens ?
thanks.

What is the difference between #BeforeClass and Spring #TestExecutionListener beforeTestClass()

What is the difference between using JUnit #BeforeClass and the Spring #TestExecutionListener beforeTestClass(TestContext testContext) "hook"? If there is a difference, which one to use under which circumstances?
Maven Dependencies:
spring-core:3.0.6.RELEASE
spring-context:3.0.6.RELEASE
spring-test:3.0.6.RELEASE
spring-data-commons-core:1.2.0.M1
spring-data-mongodb:1.0.0.M4
mongo-java-driver:2.7.3
junit:4.9
cglib:2.2
Using JUnit #BeforeClass annotation:
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
#ContextConfiguration(locations = { "classpath:test-config.xml" })
public class TestNothing extends AbstractJUnit4SpringContextTests {
#Autowired
PersonRepository repo;
#BeforeClass
public static void runBefore() {
System.out.println("#BeforeClass: set up.");
}
#Test
public void testInit() {
Assert.assertTrue(repo.findAll().size() == 0 );
}
}
=> #BeforeClass: set up.
=> Process finished with exit code 0
Using the Spring hook:
(1) Override beforeTestClass(TextContext testContext):
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
public class BeforeClassHook extends AbstractTestExecutionListener {
public BeforeClassHook() { }
#Override
public void beforeTestClass(TestContext testContext) {
System.out.println("BeforeClassHook.beforeTestClass(): set up.");
}
}
(2) Use #TestExecutionListeners annotation:
import org.springframework.test.context.TestExecutionListeners;
// other imports are the same
#ContextConfiguration(locations = { "classpath:test-config.xml" })
#TestExecutionListeners(BeforeClassHook.class)
public class TestNothing extends AbstractJUnit4SpringContextTests {
#Autowired
PersonRepository repo;
#Test
public void testInit() {
Assert.assertTrue(repo.findAll().size() == 0 );
}
}
=> BeforeClassHook.beforeTestClass(): set up.
=> Process finished with exit code 0
TestExecutionListeners are a way to externalize reusable code that instruments your tests.
As such, if you implement a TestExecutionListener you can reuse it across test class hierarchies and potentially across projects, depending on your needs.
On the flip side, a #BeforeClass method can naturally only be used within a single test class hierarchy.
Note, however, that JUnit also supports Rules: if you implement org.junit.rules.TestRule you can declare it as a #ClassRule to achieve the same thing... with the added benefit that a JUnit Rule can be reused just like a Spring TestExecutionListener.
So it really depends on your use case. If you only need to use the "before class" functionality in a single test class or a single test class hierarchy, then you'd be better off going the simple route of just implementing a #BeforeClass method. However, if you foresee that you will need the "before class" functionality in different test class hierarchies or across projects, you should consider implementing a custom TestExecutionListener or JUnit Rule.
The benefit of a Spring TestExecutionListener over a JUnit Rule is that a TestExecutionListener has access to the TestContext and therefore access to the Spring ApplicationContext which a JUnit Rule would not have access to. Furthermore, a TestExecutionListener can be automatically discovered and ordered.
Related Resources:
SPR-8854
Regards,
Sam (author of the Spring TestContext Framework)
The first solution with #BeforeClass doesn't have application context loaded. I did exteneded AbstractJUnit4SpringContextTests and defined #ContextConfiguration.
I think listner is the only way to get context loaded before #beforeclass method. Or even better extending SpringJUnit4ClassRunner class as mentioned here

Passivation issue with Stateful Session Bean

I'm using JBoss 6.1 Final, and get the following error message after my web application is running for a while (note the application doesn't crash), followed by a very long stack trace. I notice that this problem only occurs with stateful session beans that have other stateful session beans injected into them.
16:10:59,769 ERROR [org.jboss.ejb3.cache.simple.SimpleStatefulCache.UutSerialNumberServiceBean] problem passivation thread: javax.ejb.EJBException: Could not passivate; failed to save state
Here is the offending stateful session bean...
package com.ray.TEI.ejb;
import java.io.Serializable;
import javax.ejb.Stateful;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import com.ray.TEI.model.TestProcedure;
import com.ray.TEI.model.Uut;
import com.ray.TEI.model.UutSerialNumber;
#Stateful
public class UutSerialNumberServiceBean implements Serializable {
private static final long serialVersionUID = 1L;
#PersistenceContext(unitName="jasoni", type=PersistenceContextType.EXTENDED)
protected EntityManager em;
#Inject private ExecProcedureServiceBean execProcedureServiceBean;
public boolean isDuplicateSerialNumber(Uut uut, String serialNumber) {
return ((Number)em.createNamedQuery("UutSerialNumber.getCountByUutIdAndSerialNumber")
.setParameter("uut", uut)
.setParameter("serialNumber", serialNumber)
.getSingleResult()).intValue() > 0;
}
public UutSerialNumber findUutSerialNumberByUutSerialNumberId(Integer uutSerialNumberId) {
return em.find(UutSerialNumber.class, uutSerialNumberId);
}
public UutSerialNumber editSerialNumber(Integer uutSerialNumberId, String serialNumber) {
UutSerialNumber uutSerialNumber = findUutSerialNumberByUutSerialNumberId(uutSerialNumberId);
uutSerialNumber.setSerialNumber(serialNumber);
return uutSerialNumber;
}
public UutSerialNumber createSerialNumber(Uut uut, String serialNumber) {
UutSerialNumber uutSerialNumber = new UutSerialNumber();
uutSerialNumber.setSerialNumber(serialNumber);
uutSerialNumber.setUut(uut);
uut.getSerialNumbers().add(uutSerialNumber);
em.persist(uutSerialNumber);
for (TestProcedure testProcedure : uut.getTestProcedures()) {
execProcedureServiceBean.createExecProcedure(uutSerialNumber, testProcedure);
}
return uutSerialNumber;
}
}
Here is the injected stateful session bean...
package com.ray.TEI.ejb;
import java.io.Serializable;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import com.ray.TEI.model.ExecProcedure;
import com.ray.TEI.model.TestProcedure;
import com.ray.TEI.model.UutSerialNumber;
#Stateful
public class ExecProcedureServiceBean implements Serializable {
private static final long serialVersionUID = 1L;
#PersistenceContext(unitName="jasoni", type=PersistenceContextType.EXTENDED)
protected EntityManager em;
public ExecProcedure createExecProcedure(UutSerialNumber uutSerialNumber, TestProcedure testProcedure) {
ExecProcedure execProcedure = new ExecProcedure();
execProcedure.setUutSerialNumber(uutSerialNumber);
execProcedure.setTestProcedure(testProcedure);
execProcedure.setIterationCount(0);
em.persist(execProcedure);
return execProcedure;
}
}
anyone know what's wrong with this?
Thanks,
Jason
EntityManager is not serializable, I guess that's why it fails.
Couple of options from here:
deactivate passivation (easiest option in case you don't need that mechanism)
remove persistence-context from SFSB (this will most likely kill your EXTENDED mode)
replace EntityManager with Hibernate-Session, which is serializable (consider that experimental, I've never tried it out myself)