I am trying to inject a service into my bean but it is always null.
I get the following error: WELD-001000 Error resolving property userBean against base null.
Some code snippets:
index.xhtml
<h:body>
Hello from Facelets
#{userBean.name}
</h:body>
userbean.java
package beans;
import Domain.User;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import service.UserService;
#Named
#SessionScoped
public class UserBean implements Serializable{
#Inject UserService service;
private User user;
public UserBean(){
this.user = service.find_user("foo");
}
public String getName(){
return "bar";
}
}
UserService.java
package service;
import Domain.User;
import javax.ejb.Stateless;
import javax.inject.Named;
#Named
#Stateless
public class UserService {
public UserService(){}
public User find_user(String name){
return new User();
}
}
Another alternative is use #PostConstruct method annotation.
#SessionScoped
public class UserBean implements Serializable {
#Inject UserService service;
private User user;
public UserBean() {
}
#PostConstruct
void init(){
this.user = service.findUser("kaas");
}
}
Read docs
The error message could be a hint, that the JVM wasn't able to create an instance of UserBean. The following is some guessing and would have to be proven:
Dependecy Injection requires a dependency injector, a tool that injects an instance of UserService into a UserBean. In your code you're already using this injected instance during instantiation of the bean: you call the injected service in the constructor.
If the dependency injector starts it's work after the bean is created, then the call to the service inside the constructor will raise a NullPointerException (because service is still null at that time). It's worth checking that by trying to catch NPEs in the UserBean constructor for a moment. If you catch one - voilà - the dependency injector starts runnning after the bean has been created and, as a consequence, we can't use injected services during class instantiation (= in the constructor)
Workaround idea: implement a small service provider helper class - inner class could work:
public class UserBean implements Serializable {
static class UserServiceProvider {
#Inject static UserService service;
}
// ...
public UserBean() {
this.user = UserServiceProvider.service.findUser("kaas");
}
// ...
}
Untested but could work - the service should be injected in the provider class before you use it in the beans constructor.
Related
I am working on an application which uses some third java libraries which are build on top of core spring framework.
Now when my application uses these libraries I am getting ConflictingBeanDefinitionException because two libraries have the same bean name.
Now as these libraries are external I cannot change the bean name. Is there a way by which in my application I can use both the beans in same container?
#Component
class ApplicationLogic {
#Autowire FetcherAndResolver fetchFromLibraryA;
#Autowire FetcherAndResolver fetchFromLibraryB; //Because both bean names are same here comes the exception.
}
I think this would require a bit of a hack.
First of all, structure your packages in a way so that external beans are not added automatically.
So, if external class is located in package a.b. Then you have to move your own classes in either a.c or a.b.c. THis will ensure that you are in control of how beans are initialized.
Once this is done, you can add a #Configuration class where you can create Beans of both type:
#Configuration
public class ExternalBeanConfiguration {
#Bean("internal-resolver" )
public FetcherAndResolver internalResolver() {
return new FetcherAndResolver();
}
#Bean("external-resolver" )
public a.b.c.FetcherAndResolver externalResolver() {
return new a.b.c.FetcherAndResolver();
}
}
I am assuming that FetcherAndResolver is a class rather than an interface. If it is an interface, it is easier to do it as you won't have to use fully-qualified name for classes.
Then you can simply autowire with qualifiers.
#Component
public class SomeComponent {
#Qualifier( "internal-resolver" )
FetcherAndResolver internalResolver;
#Qualifier( "external-resolver" )
FetcherAndResolver externalResolver;
}
First component from third java libraries:
package com.example.component1;
import org.springframework.stereotype.Component;
#Component
public class MyComponent {
public String makeSomeWork() {
return "Component 1";
}
}
Second component from third java libraries:
package com.example.component2;
import org.springframework.stereotype.Component;
#Component
public class MyComponent {
public String makeSomeWork() {
return "Component 2";
}
}
Controller:
package com.example.controller;
import com.example.component1.MyComponent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class MyController {
#Autowired
private MyComponent myComponent;
#Autowired
private com.example.component2.MyComponent myComponent2;
#RequestMapping("/components")
public String getComponents() {
return myComponent.makeSomeWork() + "_" + myComponent2.makeSomeWork();
}
}
I'm trying to autowire an attribute (myService) which is tagged as a #Service, inside a #Configuration class, but I get a NullPointer.
If instead, I autowire myService in non-configuration classes, I have no issues.
Here's the #Service I'm having issues autowiring:
package com.myapp.resources;
#Service
class MyService {
public List<String> getRoutingKeys() {
List<String> routingKeys;
//Do stuff
return routingKeys;
}
public String aMethod() {
return "hello";
}
}
Here's the #Configuration class where I can't autowire the Service
package com.myapp.messaging;
import com.myapp.resources;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
#Configuration
public class RabbitConfiguration {
private List<String> routingKeys = writeRoutingKeys();
#Autowired
private MyService myService;
private List<String> writeRoutingKeys() {
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: true!!!
return myService.getRoutingKeys(); //here I get a NullPointer
}
//Methods with bean declarations for RabbitMQ
}
If it helps, here's my mainclass:
package com.myapp;
import com.myapp.resources;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import java.util.List;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext appContext = SpringApplication.run(Application.class, args);
MyService myService = (MyService) appContext.getBean(MyService.class);
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: false
//Do stuff
}
}
If it helps, here's a different class (a #RestController) where I'm able to autowire the service
package com.myapp.resources;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class MyController {
#Autowired
private MyService myService;
#GetMapping("/endpoint")
public String myRestMethod() {
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: false
return myService.aMethod();
}
}
I've also tried adding the #ComponentScan in the Configuration class, but I still get a NullPointer
package com.myapp.messaging;
//list of imports...
#Configuration
#ComponentScan("com.myapp.demo")
public class RabbitConfiguration {
#Autowired
private MyService myService;
//...
}
Spring will only inject the dependencies after or when a bean is instantiated (Depending if constructor injection is used or not). However , you are now accessing the dependency MyService during the field initialisation which happens before initialising a bean .Hence , it cannot access MyService during field initialisation as it is not injected yet.
You can simply fix it by changing to use constructor injection and initialise routingKeys inside a constructor at the same time :
#Configuration
public class RabbitConfiguration {
private List<String> routingKeys ;
private MyService myService;
#Autowired
public RabbitConfiguration(MyService myService){
this.myService = myService
this.routingKeys = writeRoutingKeys();
}
private List<String> writeRoutingKeys() {
return myService.getRoutingKeys();
}
}
Or simply :
#Autowired
public RabbitConfiguration(MyService myService){
this.myService = myService
this.routingKeys = myService.getRoutingKeys();
}
I would suggest injecting the service through any #Bean creation method that needs it:
#Bean
public MyBean create(MyService myService)
and then pass the service into the writeRoutingKeys(MyService myService) method to process it accordingly.
Per documentation:
#Configuration classes are processed quite early during the
initialization of the context and forcing a dependency to be injected
this way may lead to unexpected early initialization. Whenever
possible, resort to parameter-based injection as in the example above.
I'm trying to use Spring's autowire annotation in my test class in order to inject an instance of a class.
package com.mycom.mycust.processing.tasks.references;
public class ReferenceIdentifierTest {
#Autowired
private FormsDB formsDB;
#PostConstruct
#Test
public void testCreateTopLevelReferencesFrom() throws Exception {
ReferenceIdentifier referenceIdentifier = new ReferenceIdentifier(formsDB);
}
}
This is the FormsDB class:
package com.mycom.mycust.mysql;
import org.springframework.stereotype.Component;
import java.sql.SQLException;
#Component
public class FormsDB extends KeyedDBTable<Form> {
public FormsDB(ConnectionFactory factory) throws SQLException {
super(factory.from("former", new FormsObjectMapper()));
}
}
And here is the SpringBootApplication class:
package com.mycom.mycust.processing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
#ComponentScan("com.mycom.mycust")
public class Processing implements CommandLineRunner {
// Code
}
When I run my test, formsDB is null. Since I've used the PostConstruct annotation on the test function I think that FormsDB could not be autowired due to the class not being found. There is also an IntelliJ warning on the Autowired annotation in test class: Autowired members must be defined in valid Spring bean (#Component|#Service...). But I have put the Component annotation above the FormsDB class and I've also put the path com.mycom.mycust in the ComponentScan annotation of the SpringBootApplication. So I can't see why it can't find the class.
What is wrong here?
Your test calls is missing some important annotations to make autowiring work:
#SpringBootTest
#RunWith(SpringRunner.class)
public class ReferenceIdentifierTest {
#Autowired
private FormsDB formsDB;
#Test
public void testCreateTopLevelReferencesFrom() throws Exception {
ReferenceIdentifier referenceIdentifier = new ReferenceIdentifier(formsDB);
}
}
also you can remove #PostConstruct that does not make sense in a test.
When I start my spring-boot app I have this message:
APPLICATION FAILED TO START
Description:
Field userDAO in com.gisapp.services.impl.UserService required a bean
of type 'com.gisapp.gisapp.dao.IUserDAO' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.gisapp.gisapp.dao.IUserDAO' in
your configuration.
What I have read in other post related to this problem is that I have to configure the annotation #ComponentScan, but it does not work
MAIN CLASS:
package com.gisapp.gisapp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
#ComponentScan("com.gisapp")
public class GisappApplication {
public static void main(String[] args) {
SpringApplication.run(GisappApplication.class, args);
}
}
SERVICE CLASS
#Service
public class UserService implements IUserService {
#Autowired
IUserDAO userDAO;
#Override
#Transactional(readOnly=true)
public Object login() {
return userDAO.login();
}
}
- UserDAO
package com.gisapp.gisapp.dao.impl;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import com.gisapp.gisapp.dao.IUserDAO;
import com.gisapp.models.entity.User;
public class UserDAO implements IUserDAO{
#Override
public Object login() {
StringBuilder query = new StringBuilder();
query.append("SELECT * FROM User");
EntityManager em = null;
Query q = em.createNativeQuery(query.toString());
List<User> result=q.getResultList();
return result;
}
}
IUserDAO should be recognised as a bean and the app should run
1) Add a #Repository annotation in order for the DAO to be loaded as a bean into the spring context:
#Repository
public class UserDAO implements IUserDAO{
2) Just on the side.. you should most likely inject the EntityManager in it also:
#PersistenceContext
private EntityManager em;
I'm trying to create a Java EE application with #Named component.
import javax.inject.Named;
#Named
public class MyNamedBean {
public int myMethod() { ... }
}
But for some reasons, I need to access to this named java bean's methods from another java bean. So how can I do it ? Should I use #Inject annotation ?
I don't know what tag should be added. Please edit the question if needed.
Yes, the annotation #Inject can be used to inject the bean MyNamedBean to another bean, then access the method wanted from the injected bean.
Example :
Zoo.java
import javax.inject.Inject;
public class Zoo {
#Inject
private Dog dog;
public Zoo() {
}
public void talk() {
dog.talk();
}
}
Dog.java
import javax.inject.Named;
import javax.inject.Singleton;
#Named
#Singleton // optional
public class Dog {
public void talk() {
System.out.println("wowowo~ ฅ^•ﻌ•^ฅ");
}
}