Singleton CDI #Inject null pointer exception - java

I need to fire events from some ejb (Stateless and Singleton) using dependency injection. I do not use Spring, Guice etc.
The problem is that I get NPE in one of beans when calling its method through getInstance(). Here is the code snippet:
#Stateless
#LocalBean
public class ControllerStartStop {
#Inject
private Event<SomeWebMessage> webEvent;
public String startCircle(String passwordP, String passwordH) {
.........
String res = "some msg";
webEvent.fire(new SomeWebMessage(res, 0)); // this works fine
MainDay.getInstance().startDay(); // NullPointerException
Here is MainDay singleton:
#Singleton
public class MainDay {
private static final MainDay mDay = new MainDay();
public static MainDay getInstance() { return mDay ; }
#Inject
private Event<SomeWebMessage> webEvent;
public void startDay() {
String s = new String("MainDay");
webEvent.fire(new SomeWebMessage(s,0)); // NullPointerException
beans.xml is in META-INF:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
</beans>
There is no NPE when I fire event from a call of static method like MainDay.initDS() or when method startDay() is invoked by a Sheduler (#Schedule(hour = "", minute = "", second = "/10")*.
I have no idea what is the reason

Note that #Singleton means that the container (EJB or CDI, depends on which annotation it is) will manage the instance, i.e. you shouldn't create it yourself.
If you create the instance via private static final MainDay mDay = new MainDay(); there won't be any injection by the container and thus webEvent will be null. Besides that the container won't know about that instance and using #Inject MainDay somewhere else is very likely to produce another instance.
Thus just use inject (or lookups if you need to) directly:
class ControllerStartStop {
#Inject
private MainDay mDay;
...
public String startCircle(String passwordP, String passwordH) {
...
String res = "some msg";
webEvent.fire(new SomeWebMessage(res, 0));
mDay.startDay();
...
}
There is no NPE when I fire event from a call of static method like MainDay.initDS() or when method startDay() is invoked by a Sheduler (#Schedule(hour = "", minute = "", second = "/10")*. I have no idea what is the reason
Without knowing your code it's only a guess but I'd assume you're injecting MainDay here or using a CDI/JNDI lookup. Hence the container will create an instance if there is none and will inject the Event objects.

NPE 1:
Shouldn't the targetted EJB MainDay "observe" the event and call its startDay() method?
public void onEvent(#Observes SomeWebMessage event) {
// if (...)
startDay();
}
So there is no need for a static getInstance() method.
NPE 2:
#Inject Event<SomeWebMessage> webEvent;
Dependency injection (DI) only works, if you do not manually call the constructor new MainDay() but inject instances of the wanted bean and let the DI container handle construction.
But with #Observes (javax.enterprise.event.Observes) you should be able to remove all the smelly static stuff anyway.

Related

How to access configuration in a Lagom service at startup?

I am migrating my current app in Spring/J2EE to Lagom. I am working in Java. I need to read variables from the configuration (application.conf in resources folder). In the implementation module, I try to inject configuration as a class variable like this
#Inject
private Configuration config
but when I access this config object in the constructor, it gives null pointer exception.
The whole code is like this
import play.Configuration;
public class SomeServiceImpl implements SomeService {
#Inject
private Configuration config;
public SomeServiceImpl() {
//getting configuration from application.conf
// gives exception as config is null.
String key = config.getString(“key”);
}
#Override
public ServiceCall<Request, Response> send() {
//works here, does not give exception
String key = config.getString(“key”);
}
}
Sorry, I should have been clear from the beginning. I have edited the original question. I get null pointer exception when I try to read from configuration object in constructor but I am able to use it in service call implementation. I want some way in which I can access the configuration in application.conf at startup and possibly store in some config class which can be accessed anywhere later.
In Java, when an object is instantiated, the first thing that happens (before anything else can possibly happen) is the constructor is invoked. After that, frameworks like Guice (which Lagom uses) are free to inject things, but they can't do it until the constructor has been invoked. So, all your #Inject annotated fields will be null when the constructor is invoked, there is nothing you can do to work around that.
So, don't use field injection, use constructor injection, eg:
import play.Configuration;
public class SomeServiceImpl implements SomeService {
private final Configuration config;
#Inject
public SomeServiceImpl(Configuration config) {
this.config = config;
String key = config.getString("key");
}
#Override
public ServiceCall<Request, Response> send() {
String key = config.getString("key");
}
}
Constructor injection is not just recommended for this use case, you should be using it everywhere, it avoids all these potential issues.

A known design pattern for dynamic factory

Does this have a proper name?
public class SomethingFactory {
private final String someParameter;
public SomethingFactory(String someParameter) {
this.someParameter = someParameter;
}
public Something create(String anotherParameter) {
return new Something(someParameter, anotherParameter);
}
}
public class Something {
public final String someParameter;
public final String anotherParameter;
public Something(String someParameter, String anotherParameter) {
this.someParameter = someParameter;
this.anotherParameter = anotherParameter;
}
}
What's different from a regular factory is that you have to specify a parameter at runtime to create() whenever you need to create an object.
That way you can make a singleton factory within Spring context for example, configuring first half of parameters there, and then finish with the rest of parameters at runtime when you call create().
Why I need that in the first place if you're curious:
I used to have regular singleton objects in Spring context and it was fine in thread-per-request applications, but now my whole app is non-blocking and I can't use ThreadLocal to keep stuff throughout entire request processing. For example, to keep info on timings with something like Apache StopWatch.
I needed to find a way to implement a "request scope" in a multithreading, non-blocking environment without having to supply the object representing the scope in every method (that would be silly) of my code.
So I thought let's make every (service) class take this scope object in constructor and let's create those classes on every request, but that goes against the singletons. The singletons we're talking are like, UserService that logs a user in, or a CryptoService that generates digital signatures. They're configured once in Spring, injected wheneven needed and everything's ok. But now I need to create those service classes in every method where they're needed, instead of just referencing an injected singleton instance.
So I thought let's call those singletons "templates" and whenever you need an actual instance you call create() supplying the said scope object. That way every class has the scope object, you just have to keep supplying it into other template service constructors. The full thing would look like this:
public class UserService {
private final Scope scope;
private final Template t;
private UserService(Template t, Scope scope) {
this.t = t;
this.scope = scope;
}
public void login(String username) {
scope.timings.probe("before calling database");
t.database.doSomething(username);
scope.timings.probe("after calling database");
}
public static class Template { /* The singleton configured in Spring */
private Database database;
public void setDatabase(Database database) { /* Injected by Spring */
this.database = database;
}
public UserService create(Scope scope) {
return new UserService(this, scope);
}
}
}
public class LoginHttpHandler { /* Also a Spring singleton */
private UserService.Template userServiceT;
public void setUserServiceT(UserService.Template userServiceT) { /* Injected by Spring */
this.userServiceT = userServiceT;
}
public void handle(HttpContext context) { /* Called on every http request */
userServiceT.create(context.scope).login("billgates");
}
}
In Spring you'd just describe a UserService.Template bean with the appropriate dependencies it needs and then inject that bean whenever a UserService is needed.
I just call that a "template". But like always I feel it's already been done. Does it have any name?
That is almost the example given for Guice's AssistedInject:
public class RealPaymentFactory implements PaymentFactory {
private final Provider<CreditService> creditServiceProvider;
private final Provider<AuthService> authServiceProvider;
#Inject
public RealPaymentFactory(Provider<CreditService> creditServiceProvider, Provider<AuthService> authServiceProvider) {
this.creditServiceProvider = creditServiceProvider;
this.authServiceProvider = authServiceProvider;
}
public Payment create(Date startDate, Money amount) {
return new RealPayment(creditServiceProvider.get(), authServiceProvider.get(), startDate, amount);
}
}
public class RealPayment implements Payment {
public RealPayment(
CreditService creditService, // from the Injector
AuthService authService, // from the Injector
Date startDate, // from the instance's creator
Money amount) // from the instance's creator
{
...
}
}
Assisted injection is used to "create classes that need extra arguments at construction time".
Also, this is similar to partial application, so you could have a PartialUserService that creates a UserService.

Cdi constructor injection ejb

I downloaded intelliJ which gives me an advice to put my injections in a constructor. However when doing what they advice I have an other advice message telling me I need an empty constructor. So I'm wondering what's the best way to implement something like this :
That is just a background task in a jsf application that run every minute.
#Singleton
public class MatchesBgService implements Serializable {
#Inject //intelliJmessage : Hey, you should use constructor injection
private MatchLookup ml;
#Inject
private MatchTask bgTask;
public MatchesBgService(){
comparator = new MatchComparator();
}
#Schedule(hour = "*", minute = "*/1", second = "20", persistent = false)
public void gettingMatches() {
Your code might look like this:
#Singleton
public class MatchesBgService implements Serializable {
private final MatchLookup ml;
private final MatchTask bgTask;
#Inject
public MatchesBgService(MatchLookup ml, MatchTask bgTask){
this.ml = ml;
this.bgTask = bgTask;
// ...
}
}
Answering your doubts:
It's considered a good practice to use a constructor injection wherever it makes sense.
CDI spec says you need a default empty constructor (to have class proxyable).
But fortunately, at least Weld doesn't require it - so my above code will
work just fine.
That is why IntelliJ gives you these advices.
Cheers

DeltaSpike custom ConfigSource with CDI

I am trying to define a custom DeltaSpike ConfigSource. The custom config source will have the highest priority and check the database for the config parameter.
I have a ConfigParameter entity, that simply has a key and a value.
#Entity
#Cacheable
public class ConfigParameter ... {
private String key;
private String value;
}
I have a #Dependent DAO that finds all config parameters.
What I am trying to do now, is define a custom ConfigSource, that is able to get the config parameter from the database. Therefore, I want to inject my DAO in the ConfigSource. So basically something like
#ApplicationScoped
public class DatabaseConfigSource implements ConfigSource {
#Inject
private ConfigParameterDao configParameterDao;
....
}
However, when registering the ConfigSource via META-INF/services/org.apache.deltaspike.core.spi.config.ConfigSource, the class will be instantiated and CDI will not work.
Is there any way to get CDI working in this case?
Thanks in advance, if you need any further information, please let me know.
The main problem is, that the ConfigSource gets instantiated very early on when the BeanManager is not available yet. Even the JNDI lookup does not work at that point in time. Thus, I need to delay the injection/lookup.
What I did now, is add a static boolean to my config source, that I set manually. We have a InitializerService that makes sure that the system is setup properly. At the end of the initialization process, I call allowInitialization() in order to tell the config source, that the bean is injectable now. Next time the ConfigSource is asked, it will be able to inject the bean using BeanProvider.injectFields.
public class DatabaseConfigSource implements ConfigSource {
private static boolean allowInit;
#Inject
private ConfigParameterProvider configParameterProvider;
#Override
public int getOrdinal() {
return 500;
}
#Override
public String getPropertyValue(String key) {
initIfNecessary();
if (configParameterProvider == null) {
return null;
}
return configParameterProvider.getProperty(key);
}
public static void allowInitialization() {
allowInit = true;
}
private void initIfNecessary() {
if (allowInit) {
BeanProvider.injectFields(this);
}
}
}
I have a request-scoped bean that holds all my config variables for type-safe access.
#RequestScoped
public class Configuration {
#Inject
#ConfigProperty(name = "myProperty")
private String myProperty;
#Inject
#ConfigProperty(name = "myProperty2")
private String myProperty2;
....
}
When injecting the Configuration class in a different bean, each ConfigProperty will be resolved. Since my custom DatabaseConfigSource has the highest ordinal (500), it will be used for property resolution first. If the property is not found, it will delegate the resolution to the next ConfigSource.
For each ConfigProperty the getPropertyValue function from the DatabaseConfigSource is called. Since I do not want to retreive the parameters from the database for each config property, I moved the config property resolution to a request-scoped bean.
#RequestScoped
public class ConfigParameterProvider {
#Inject
private ConfigParameterDao configParameterDao;
private Map<String, String> configParameters = new HashMap<>();
#PostConstruct
public void init() {
List<ConfigParameter> configParams = configParameterDao.findAll();
configParameters = configParams.stream()
.collect(toMap(ConfigParameter::getId, ConfigParameter::getValue));
}
public String getProperty(String key) {
return configParameters.get(key);
}
}
I could sure change the request-scoped ConfigParameterProvider to ApplicationScoped. However, we have a multi-tenant setup and the parameters need to be resolved per request.
As you can see, this is a bit hacky, because we need to explicitly tell the ConfigSource, when it is allowed to be instantiated properly (inject the bean).
I would prefer a standarized solution from DeltaSpike for using CDI in a ConfigSource. If you have any idea on how to properly realise this, please let me know.
Even though this post has been answered already I'd like to suggest another possible solution for this problem.
I managed to load properties from my db service by creating an #Signleton #Startup EJB which extends the org.apache.deltaspike.core.impl.config.BaseConfigSource and injects my DAO as delegate which I then registered into the org.apache.deltaspike.core.api.config.ConfigResolver.
#Startup
#Singleton
public class DatabaseConfigSourceBean extends BaseConfigSource {
private static final Logger logger = LoggerFactory.getLogger(DatabaseConfigSourceBean.class);
private #Inject PropertyService delegateService;
#PostConstruct
public void onStartup() {
ConfigResolver.addConfigSources(Collections.singletonList(this));
logger.info("Registered the DatabaseConfigSourceBean in the ConfigSourceProvider ...");
}
#Override
public Map<String, String> getProperties() {
return delegateService.getProperties();
}
#Override
public String getPropertyValue(String key) {
return delegateService.getPropertyValue(key);
}
#Override
public String getConfigName() {
return DatabaseConfigSourceBean.class.getSimpleName();
}
#Override
public boolean isScannable() {
return true;
}
}
I know that creating an EJB for this purpose basically produces a way too big overhead, but I think it's a bit of a cleaner solution instead of handling this problem by some marker booleans with static accessors ...
DS is using the java se spi mechanism for this which is not CD'Injectable'. One solution would be to use the BeanProvider to get hold of your DatabaseConfigSource and delegate operations to it.

Spring #Autowired chains and regular 'new XYZ()' instantiations

Is my impression correct that by using the regular new XYZ() way of instantiating some component XYZ prevents Spring from processing the #Autowired fields inside XYZ?
Second question: is it correct that I cannot use dependency injection in XYZ and at the same time use final fields in XYZ because of that? Example:
#Component
public class XYZ {
#Autowired
private SomeDep dep;
private final int value;
public XYZ(int value) {
this.value = value;
}
}
How would I make that working?
So, well, accepting there is no nicer way, let's do it that way:
#Component
public class XYZ {
#Autowired
private SomeDep dep;
private final int value;
// factory instantiation
XYZ() {
value=0;
}
private XYZ(SomeDep dep, int value) {
this.dep = dep;
this.value = value;
}
public XYZ getInstance(int value) {
return new XYZ(dep, value);
}
}
??? That is ugly. And it gets even uglier when I want to move the dependency declaration to a parent class....... ??? I always thought DI is nice. I think I have to reconsider that. What are the alternatives? Am I missing something?
If you create object with new, #Autowired won't work, because this object is created outside of the Spring IoC container. So this object should be instantiated by spring in order to let it inject dependencies. To get this object (bean) from container (spring application context), you should initialize Spring context and call context.getBean("beanName").
You can use constructor dependency injection here. Here you can read more about injection types

Categories