I can't figure out why all my beans are null in the controller. I understand that this is a common question but I am not instantiating the object with new.
Controller:
#Controller
#RequestMapping("/store")
public class MyController {
#Autowired
private MyService myService;
#GetMapping("/getOptions")
private String getOptions(HttpServletRequest request)
{
myService.doSomething(request);
....
}
}
When I request http://localhost/store/getOptions I get a NullPointerException on myService.
MyService
#Service
public class MyService
{
....
}
WebConfig
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
BeanNameUrlHandlerMapping beanNameUrlHandlerMapping()
{
return new BeanNameUrlHandlerMapping();
}
}
Main
#SpringBootApplication
#Configuration
#ComponentScan(basePackages = { "com.mypackage.config", "com.mypackage.service", "com.mypackage.controller"})
public class MyApplication
{
public static void main(String[] args)
{
if (AuthConfigFactory.getFactory() == null)
AuthConfigFactory.setFactory(new AuthConfigFactoryImpl());
SpringApplication.run(MyApplication.class, args);
}
}
When I start the application, I can see in the logs that the myService bean is actually being Autowired into the controller:
- Processing injected element of bean 'myController': AutowiredFieldElement for private com.mypackage.service.MyService com.mypackage.controller.MyController.myService
- Returning cached instance of singleton bean 'MyService'
- Autowiring by type from bean name 'myController' to bean named 'myService'
So I don't understand why when I try to access myService within the controller, it is null. I do not instantiate the controller anywhere with new.
Clipped Exception
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause:
java.lang.NullPointerException: null
at com.mypackage.controller.MyController.getOptions(MyController.java)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
....
Edit:
I've removed web.xml from my project, as it is irrelevant.
My problem was that some of the methods in my controller were annotated as #Transactional. I did not provide enough information in my original post for anyone to figure that out. I found the answer here: Why we shouldn't make a Spring MVC controller #Transactional?
Spring java configuration:
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter{
#Bean
BeanNameUrlHandlerMapping beanNameUrlHandlerMapping(){
return new BeanNameUrlHandlerMapping();
}
}
Service class:
#Service("myService")
public class MyServiceImpl implements MyService{
#Override
public String getMessageinfo() {
// TODO Auto-generated method stub
return "Hello World!!";
}
}
Service interface:
public interface MyService {
public String getMessageinfo();
}
Controller class:
#RestController
#RequestMapping("/hello")
public class MyController {
#Autowired
private MyService myService;
#GetMapping("/getMessage")
//#ResponseBody
private String getMessage(HttpServletRequest req){
System.out.println("inside controller : - "+myService.getMessageinfo());
return myService.getMessageinfo();
}
}
SpringbootMain
#SpringBootApplication
#Configuration
#ComponentScan(basePackages={"com.example.demo.config","com.example.demo.controller","com.example.demo.service"})
public class Demo1Application {
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
}
}
This worked for me. without exception, but i used eclipse STS IDE and created Spring boot project.
http://localhost:8080/hello/getMessage
Related
I have a setup Spring + Apache CXF and I'm trying to make CustomerWebServiceImpl injectable. To do this I should inject it within #Autowired WebServiceConfig. When I do this, the WebServiceConfig doesn't even run(checked via debugger). In stack trace I see the following exception:
NoSuchBeanDefinitionException: No qualifying bean of type 'com.beginnercourse.softcomputer.domains.customer.CustomerWebService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
I've checked spring annotations, everything marked with #Component/#Service. Made sure that I don't initialize any of these beans with new. Tried to replace field autowiring by setters
I have seen that there could be unexpected problems, like here
My code:
CustomerWebService
#WebService
public interface CustomerWebService {
String addCustomer(CustomerDto newCustomer);
}
CustomerWebServiceImpl
#Component
#WebService(endpointInterface = "com.soft.domains.customer.CustomerWebService")
public class CustomerWebServiceImpl implements CustomerWebService {
#Autowired
private CustomerService customerService;
#Override
public String addCustomer(CustomerDto newCustomer) {
System.out.println("Hello world");
customerService.create(new CustomerEntity());
return "Hello " + newCustomer.getName();
}
}
WebServiceConfig
#Configuration
public class WebServiceConfig {
#Autowired
private CustomerWebService customerWebService;
#Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
#Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), customerWebService);
endpoint.publish("http://localhost:8080/services/customer");
return endpoint;
}
}
UPD: I seems like only one of my configuration classes(RootConfig) is initialized fine. Others are not initializing beans. Maybe WebApplicationInitializer.onStartup expect another configuration. Then what kind of startup should be used to run new CXFServlet() with such Configuration classes?
public class WebServiceDispatcherServletInitializer implements WebApplicationInitializer {
private static final String SERVICE_DISPATCHER_SERVLET = "service_dispatcher_servlet";
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(WebServiceConfig.class, RootConfig.class, PersistenceConfig.class);
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new CXFServlet());
dispatcher.addMapping("/services/*");
}
}
I can run my springboot project in IDEA nicely but when packed it to a jar and run with the java command, just got the java.lang.NullPointerException when getting a bean from spring context.
the first class which just got errors:
#Service
public class MdspiImpl extends CThostFtdcMdSpi {
public MdspiImpl(CThostFtdcMdApi mdapi) {
m_mdapi = mdapi;
logger.info("MdspiImpl is creating...");
***mdr = SpringContextUtil.getBean("marketDataRobot");//this is the error code***
}
}
the second class:
#Service
public class MarketDataRobot {
}
the SpringContextUtil class:
#Component("SpringContextUtil")
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static <T> T getBean(String name) {
return (T) applicationContext.getBean(name);
}
}
the gradle file:
jar {
baseName = 'programmingTrading'
version = '0.1.0'
manifest {
attributes 'Main-Class': 'com.blackHole.programmingTrading'
}
}
the running exception:
WARN main[AbstractApplicationContext.java:557 Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mdspiImpl' defined in URL [jar:file:/E:/workspace/simuPrd/programmingTrading-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/com/blackHole/programmingTrading/infrastructure/MdspiImpl.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.blackHole.programmingTrading.infrastructure.MdspiImpl]: Constructor threw exception; nested exception is java.lang.NullPointerException]
[com.blackHole.programmingTrading.infrastructure.MdspiImpl]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:184)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:300)
... 27 common frames omitted
Caused by: java.lang.NullPointerException: null
at com.blackHole.programmingTrading.SpringContextUtil.getBean(SpringContextUtil.java:35)
at com.blackHole.programmingTrading.infrastructure.MdspiImpl.<init>(MdspiImpl.java:46)
It also stem from another problem: #Autowired annotation doesn't work...
when using like this:
#Component
public class Scu{
}
in another class:
#Autowired
private Scu scu;
logger.info(String.format("MdspiImpl is creating...[%s]", scu.toString()));
will get a java.lang.NullPointerException: null
spring-boot configuration like this:
#SpringBootApplication
public class ProgrammingTrading {
public static void main(String[] args) {
SpringApplication.run(ProgrammingTrading.class, args);
}
}
that is part of reasons of using SpringContextUtil to get the bean...
thanks a lot!
SpringContextUtil shouldn't be a accessed statically like you are doing... Since you define it as a #Component do the following;
#Service
public class MdspiImpl extends CThostFtdcMdSpi {
#Autowired
private SpringContextUtil springContextUtil;
public MdspiImpl(CThostFtdcMdApi mdapi) {
m_mdapi = mdapi;
logger.info("MdspiImpl is creating...");
***mdr = springContextUtil.getBean("marketDataRobot");
}
}
Due to SpringContextUtil not being injected via Spring, but simply accessed statically, the applicationContext inside of it is ignored and is null in your case.
Also remove the static modifier;
#Component
public class SpringContextUtil implements ApplicationContextAware {
private ApplicationContext applicationContext;
// include getter/setter for applicationContext as well
public <T> T getBean(String name) {
return (T) applicationContext.getBean(name);
}
}
edit
The trouble from the latest example project;
#Service
public class ExampleService {
#Autowired
private Logger logger;
public ExampleService() {
this.logger=logger;
logger.info("Im working");
}
}
Here the Logger will be null, when the ExampleService constructor is triggered, since the constructor is called before the injection starts, but you can merge this behaviour if you incorporate the injection through the said constructor as follows;
#Service
public class ExampleService {
private final Logger logger;
public ExampleService(Logger logger) {
this.logger = logger;
logger.info("Im working");
}
}
Works perfectly without any trouble...
You should never be accessing beans programmatically like you did with this SpringContextUtil, just inject MarketDataRobot in the constructor of MdspiImpl and you’re good to go (since it’s annotated with #Service). The preferred way is to use constructor injection instead of field injection, which will make it easier for you to write unit tests. You can also get rid of #Autowired if you have only one constructor.
Service Component object is not loaded in Spring Batch processor.But which is working fine with Spring Testing.Please help me to find the solution for this.
public class PersonJobProcessor implements ItemProcessor<Person,Person> {
#Autowired
PersonService service;
#Override
public Person process(final Person person) throws Exception {
//user service variable here
}
}
Error Message:-
Action:Consider defining a bean of type 'PersonService' in your configuration.
Below configuration is working fine
#SpringBootTest
#RunWith(SpringRunner.class)
public class PersonServiceTest {
#Autowired
PersonService service;
public void testmethod(){
service.method();// works without issues
}
}
Looks like missing SpringContext inside PersonJobProcessor. Did you add #Component on this class?
Following is the service.
#Service
public class MyService {
public List<Integer> getIds(Filter filter){
// Method body
}
}
And a configuration class.
#Configuration
public static class MyApplicationContext {
#Bean
public Filter filter(ApplicationContext context) {
return new Filter();
}
}
The desired goal is a unit test to confirm getIds() returns the correct result.
See the JUnit test below.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=MyApplicationContext.class,
loader=AnnotationConfigContextLoader.class)
public class AppTest
{
#Autowired
Filter filter;
#Autowired
MyService service;
}
The compiler finds the correct bean for the Filter class but throws a BeanCreationException: Could not autowire field exception for the service variable. I've tried adding the service class to the ContextConfiguration classes attribute but that results in a IllegalStateException: Failed to load ApplicationContext exception.
How can I add MyService to ContextConfiguration?
Add the following annotation to MyApplicationContext for the service to be scanned #ComponentScan("myservice.package.name")
Add these two annotations to the test class AppTest, like in the following example:
#RunWith(SpringRunner.class )
#SpringBootTest
public class ProtocolTransactionServiceTest {
#Autowired
private ProtocolTransactionService protocolTransactionService;
}
#SpringBootTest loads the whole context.
I have several classes in a Spring Boot project, some work with #Autowired, some do not. Here my code follows:
Application.java (#Autowired works):
package com.example.myproject;
#ComponentScan(basePackages = {"com.example.myproject"})
#Configuration
#EnableAutoConfiguration
#EnableJpaRepositories(basePackages = "com.example.myproject.repository")
#PropertySource({"classpath:db.properties", "classpath:soap.properties"})
public class Application {
#Autowired
private Environment environment;
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
#Bean
public SOAPConfiguration soapConfiguration() {
SOAPConfiguration SOAPConfiguration = new SOAPConfiguration();
SOAPConfiguration.setUsername(environment.getProperty("SOAP.username"));
SOAPConfiguration.setPassword(environment.getProperty("SOAP.password"));
SOAPConfiguration.setUrl(environment.getProperty("SOAP.root"));
return SOAPConfiguration;
}
HomeController (#Autowired works):
package com.example.myproject.controller;
#Controller
class HomeController {
#Resource
MyRepository myRepository;
MyService (#Autowired does not work):
package com.example.myproject.service;
#Service
public class MyServiceImpl implements MyService {
#Autowired
public SOAPConfiguration soapConfiguration; // is null
private void init() {
log = LogFactory.getLog(MyServiceImpl.class);
log.info("starting init, soapConfiguration: " + soapConfiguration);
url = soapConfiguration.getUrl(); // booom -> NullPointerException
I do not get the SOAPConfiguration but my application breaks with a null pointer exception when I try to access it.
I have already read many Threads here and googled around, but did not find a solution yet. I tried to deliver all necessary information, please let me know if anything misses.
I guess you call init() before the autowiring takes place. Annotate init() with #PostConstruct to make it call automatically after all the spring autowiring.
EDIT: after seeing your comment, I guess you are creating it using new MyServiceImpl(). This takes away the control of the MyServiceImpl from Spring and gives it to you. Autowiring won't work in those case
Did you created a bean for the class SOAPConfiguration in any of your configuration classes? If you want to autowire a class in your project, you need to create a bean for it. For example,
#Configuration
public class SomeConfiguration{
#Bean
public SOAPConfiguration createSOAPConfiguration(){
return new SOAPConfiguration();
}
}
public class SomeOtherClass{
#Autowired
private SOAPConfiguration soapConfiguration;
}