NullPointerException with PersistenceContext EntityManager in singleton class. How can I solve this? - java

Short version: I have a singleton class that should only be initialized once per program execution. The goal of this class is to fetch constant data from the database, which lies in its own table. I've currently got the class set up like this:
public class MyService {
private static final MyService INSTANCE = new MyService();
// Evaluates to null
#PersistenceContext(unitName = "mydb")
private EntityManager myEntityManager;
private int myDbConstant;
private MyEnum myEnum;
public static getInstance() {
return INSTANCE;
}
public int getDbConstant() {
return myDbConstant;
}
public MyEnum getMyEnum() {
return myEnum;
}
private MyService() {
readValues();
}
// This method fetches the constant values from the database
private void readValues() {
List<MyEntity> constantEntities = myEntityManager.createNamedQuery(MyEntity.FIND_ALL).getResultList(); // NullPointerException
// ...
}
}
However, this always seems to result in a NullPointerException just as the entity manager tries to fetch the entities. I'm not really sure what could be causing this. My project is in an EJB container so my understanding is I'm not supposed to create the EM myself.
Is it possible that the new MyService(); is the problem? If so, how would I work around it while maintaining the singleton nature of this class?

Is your MyService class annotated with appropriate annotations like #Singletone or #Stareless ?

Related

How to limit instantiation of class and methods in it -Java

#AllArgsConstructor(onConstructor = #__({ #Inject }))
public class TransactionManager {
private final TransactionHelper tnxHelper;
public void createTransactions(List<Details> details) {
tnxHelper.createTransactions(details);
}
}
#AllArgsConstructor(onConstructor = #__({ #Inject }))
public class TransactionHelper {
private final A a;
private final B b;
public void createTransactions(List<Details> details) {
//Some logic
}
}
So in the above code, I want TransactionManager to be the main class and every interactions related to Transaction should go via it, like createTransactions.
So how can i make TransactionHelper as hidden? So that no one can use this class apart from TransactionManager?
Also is there any way to only make createTransactions in TransactionHelper as hidden, rather than hiding the whole class.
Thank you in advance!!
Is the usage of Nested classes resolve your problem ?
https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
class TransactionManager {
// you cannot use the class TransactionHelper outside the TransactionManagerClass
// you need an instance of TransactionManager to have an instance of TransactionHelper
// so within static methods here you cant use it directly
private class TransactionHelper {
}
void dooo() {
TransactionHelper t = new TransactionHelper();
}
}

How to perform an #Entity query inside a ConstraintValidator

The scenario is that before persisting a Log entity class, its property, String description should be checked if it contains at least a word found in the IllegalWord entity class. Here is the mapping of the two entity classes:
// Log.java
#Entity
public class Log {
#GeneratedValue(strategy=GenerationType.SEQUENCE)
#Id
private Long id;
#NotContainingIllegalWords
private String description;
}
// IllegalWord.java
#Entity
public class IllegalWord {
#GeneratedValue(strategy=GenerationType.SEQUENCE)
#Id
private Long id;
private String word;
}
Since I will be performing a select * to the IllegalWord entity class, I created a repository class for it:
// IllegalWordRepository.java
#Repository
public interface IllegalWordRepository extends CrudRepository<IllegalWord, Long> {}
And then created the ConstraintValidator validator class that will be used by NotContainingIllegalWords annotation, that in turn, will be use to annotate the String description field of Log entity class:
// NotContainingIllegalWordsValidator.java
public class NotContainingIllegalWordsValidator implements ConstraintValidator<NotContainingIllegalWords, Object> {
private static final Logger log = LoggerFactory.getLogger(NotContainingIllegalWordsValidator.class);
#Autowired
private IllegalWordRepository illegalWordRepository;
public void initialize(NotContainingIllegalWords constraintAnnotation) {}
public boolean isValid(String value, ConstraintValidatorContext cxt) {
log.debug("illegalWordRepository is null? " + (illegalWordRepository == null));
// Returns "illegalWordRepository is null? true"
// It is not injected even with the #Autowired annotation.
boolean valid = true;
Collection<IllegalWord> illegalWords = illegalWordRepository.findAll();
// Encounters a NullPointerException here.
// valid = ...loop through illegalWords collection and match regex (or whatever optimal approach)
// with #param value to check if it contains the illegal word.
return valid;
}
I thought it will be as straight-forward like that. But the statement illegalWordRepository.findAll() throws an error because the illegalWordRepository variable is null. Notice that I tried to check if it is null in the preceding statement.
I assumed that I have something wrong coded within the repository class so I attempted to used #Autowired private IllegalWordRepository illegalWordRepository inside a #Service annotated class and suprisingly it is injected there properly (e.i. not null):
// IllegalWordService.java
#Service
public class IllegalWordService {
private static final Logger log = LoggerFactory.getLogger(IllegalWordService.class);
#Autowired
private IllegalWordRepository illegalWordRepository;
public IllegalWord generate(String word) {
log.debug("illegalWordRepository is null? " + (illegalWordRepository == null));
// Returns "illegalWordRepository is null? false"
IllegalWord illegalWord = new IllegalWord();
illegalWord.setWord(word);
illegalWordRepository.save(illegalWord);
// Didn't encounter a NullPointerException here.
return illegalWord;
}
}
Therefore, I guess nothing is wrong with the IllegalWordRepository repository class. It's just that it is not injected in NotContainingIllegalWordsValidator validator class as I intended it to be with the #Autowired annotation (if that is how #Autowired annotation was intended to function even, I am sorry I am new in Spring Framework.).
If there is a proper approach on how to perform a #Entity query inside a ConstraintValidator instance, please tell me.
Related unanswered SO question: Inject Repository inside ConstraintValidator with Spring 4 and message interpolation configuration
Failed Attempt:
I tried to annotate the NotContainingIllegalWordsValidator class with #Configurable annotation, like so:
#Configurable(autowire=Autowire.BY_NAME, preConstruction=true)
public class NotContainingIllegalWordsValidator implements ConstraintValidator<NotContainingIllegalWords, Object> {
but the illegalWordRepository property remains null.
Since Your validator is not initialized by Spring, you can't inject anything into it. You'd have to access the ApplicationContext through a static variable.
#SpringBootApplication
public class MyApplication {
private static ApplicationContext applicationContext;
public static void main(final String[] args) {
applicationContext = SpringApplication.run(MyApplication.class, args);
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}
And in your ConstraintValidator:
public class NotContainingIllegalWordsValidator implements ConstraintValidator<NotContainingIllegalWords, Object> {
public boolean isValid(String value, ConstraintValidatorContext cxt) {
ApplicationContext applicationContext = MyApplication.getApplicationContext();
IllegalWordRepository illegalWordRepository = applicationContext.getBean(IllegalWordRepository.class);
...
}
}
From my answer to a similar question:
The minimum setup for #Autowired to work properly in ConstraintValidator implementation is to have this bean in a Spring #Configuration:
#Bean
public Validator defaultValidator() {
return new LocalValidatorFactoryBean();
}
This is the demo project

Best practice - Setting a field without setters in a unit test

Let's say you have the following class you would like to test:
public class SomeService {
public String someMethod(SomeEntity someEntity) {
return someEntity.getSomeProperty();
}
}
The SomeEntity looks like this:
public class SomeEntity {
private String someProperty;
public getSomeProperty() {
return this.someProperty;
}
}
The assertion you would like to do can be the following:
String result = someService.someMethod(someEntity);
assertThat(result).isEqualTo("someValue");
How can you make this test work?
1) Add a setter for 'someProperty' in the SomeEntity class. I don't think this a good solution because you don't change production code to make your tests work.
2) Use ReflectionUtils to set the value of this field. Test would look like this:
public class TestClass {
private SomeService someService;
#Test
public void testSomeProperty() {
SomeEntity someEntity = new SomeEntity();
ReflectionTestUtils.setField(someEntity, "someProperty", "someValue");
String result = someService.someMethod(someEntity);
assertThat(result).isEqualTo("someValue");
}
}
3) You create an inner class in your test class that extends the SomeEntity class and adds the setter for this field. However, for this to work you will also need to change the SomeEntity class because the field should become 'protected' instead of 'private'. Test class might look like this:
public class TestClass {
private SomeService someService;
#Test
public void testSomeProperty() {
SomeEntityWithSetters someEntity = new SomeEntityTestWithSetters();
someEntity.setSomeProperty("someValue");
String result = someService.someMethod(someEntity);
assertThat(result).isEqualTo("someValue");
}
public class SomeEntityWithSetters extends SomeEntity {
public setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
}
}
4) You use Mockito to mock SomeEntity. Seems fine if you only need to mock only one property in the class, but what if you need to mock like 10 properties are so. The test might look like this:
public class TestClass {
private SomeService someService;
#Test
public void testSomeProperty() {
SomeEntity someEntity = mock(SomeEntity.class);
when(someEntity.getSomeProperty()).thenReturn("someValue");
String result = someService.someMethod(someEntity);
assertThat(result).isEqualTo("someValue");
}
}
you can set the value using reflection. It doesn't need any change in production code.
ReflectionTestUtils.setField(YourClass.class, "fieldName", fieldValue);
You can add a setter with default (package private) scope.
With junit testing of SomeService.someMethod()
alternative 1. should not use this as no need to change entity for writing junit.
alternative 2. can be used.
alternative 3. again same a 3, no need to extend for just junit. how about when the class cannot be extended.
alternative 4. yes, a good option. mockito is being used for the same reason.
What is the behavior / contract specific to SomeService that is testable? Based upon your skeletal code, there really isn't any. It will either throw a NPE on bad input, or return a String that may or may not be null, depending on Hibernate magic. Not sure what you can actually test.
I have been through this same dilemma many times before, a quick solution is to make the field you want to mock package protected, or provide a protected setter. Of course both will alter production code.
Alternatively, you can consider dependency injection framework, such as Dagger. Below is an example they give:
#Module
class DripCoffeeModule {
#Provides Heater provideHeater(Executor executor) {
return new CpuHeater(executor);
}
}
This JUnit test overrides DripCoffeeModule's binding for Heater with a mock object from Mockito. The mock gets injected into the CoffeeMaker and also into the test.
public class CoffeeMakerTest {
#Inject CoffeeMaker coffeeMaker;
#Inject Heater heater;
#Before public void setUp() {
ObjectGraph.create(new TestModule()).inject(this);
}
#Module(
includes = DripCoffeeModule.class,
injects = CoffeeMakerTest.class,
overrides = true
)
static class TestModule {
#Provides #Singleton Heater provideHeater() {
return Mockito.mock(Heater.class);
}
}
#Test public void testHeaterIsTurnedOnAndThenOff() {
Mockito.when(heater.isHot()).thenReturn(true);
coffeeMaker.brew();
Mockito.verify(heater, Mockito.times(1)).on();
Mockito.verify(heater, Mockito.times(1)).off();
}
}

Understanding of Transactional services - spring

I have a service implementation with a particular method like so:
public class ExampleServiceImpl implements ExampleService {
#AutoWired
#Resource
private RecordRepository recordRepository;
private void processRecord() {
// some code here
}
#Transactional(readOnly=false)
public void processRecord(Record a) {
Record original = getOriginal(a);
recordRepository.saveChanges(a,original);
}
}
Where the Record class is the root object of an object graph. RecordRepository looks something like the following with sub repositories to save various children of the objects in the graph.
public class RecordRepository extends BaseRepository<Record> {
#AutoWired
#Resource
private IDao databaseDao;
#AutoWired
#Resource
private SubRecordRepository subRecordRepository;
public void saveChanges(Record a, Record b) {
//Perform some processing on a, b
for(SubRecord subA : a.getSubRecords()) {
subRecordRepository.saveChanges(subA);
}
databaseDao.updateRecord(a);
}
}
public class DatabaseDao extends NamedParameterJdbcDaoSupport implements IDao {
#Autowired
public DatabaseDao(#Qualifier("org.somewhere.Datasource") DataSource ds) {
super();
this.setDataSource(ds);
}
public void updateRecord(Record inRecord) {
String query = (String) sql.get("updateRecord");
SqlParameterSource parms = new BeanPropertySqlParameterSource(inRecord);
getNamedParameterJdbcTemplate().update(query, parms);
}
public void insertSubRecord(SubRecord inSubRecord) {
String query = (String) sql.get("insertSubRecord");
SqlParameterSource parms = new BeanPropertySqlParameterSource(inSubRecord);
getNamedParameterJdbcTemplate().insert(query, parms);
}
// other update and insert methods
}
Will the transaction be applied across all involved inserts\updates from the processRecord call? In other words, if an insert or update fails, will all previously called inserts and updates from ExampleServiceImpl.processRecord get rolled back?
Yes. The transactional aspect makes sure that a transaction is started before the annotated method is called, and that the transaction (if started by this method) is committed or rollbacked once the method returns.
The transactional interceptor doesn't know (and doesn't care) about which other methods are called inside the annotated method. Every read and write to the DataSource handled by the Spring transaction manager will be included in the same transaction.

What is the difference between putting #Autowired to a variable and a method?

Class A {
private B instanceB;
#Autowired
public setInstanceB(B instanceB) {
this.instanceB = instanceB;
}
}
Above one versus this one.
Class A {
#Autowired
private B instanceB;
public setInstanceB(B instanceB) {
this.instanceB = instanceB;
}
}
Will the behavior differ based on the access modifier ?
The difference is the setter will be called if that's where you put it, which is useful if it does other useful stuff, validation, etc. Usually you're comparing:
public class A {
private B instanceB;
#Autowired
public setInstanceB(B instanceB) {
this.instanceB = instanceB;
}
}
vs
public class A {
#Autowired
private B instanceB;
}
(ie there is no setter).
The first is preferable in this situation because lack of a setter makes mocking/unit testing more difficult. Even if you have a setter but autowire the data member you can create a problem if the setter does something different. This would invalidate your unit testing.

Categories