#Value Injection in Spring Boot 2.0.0 injects null - java

So. After reading the official docs and finding nothing wrong with what I am doing, I just ran out of ideas.
My application.properties:
vz.info.version=0.2.8
My properties Component
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
#Configuration
public class VZProperties {
#Value("${vz.info.version}")
#Getter
#Setter
private String apiVersion;
}
I am getting null all over the place for the apiVersion.
And Lombok does not seem to be the issue. What did I miss from the docs?
EDIT
I would like to call it like this:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.Lists;
import lombok.Getter;
import java.io.Serializable;
import java.util.List;
public class VZNFCTagResponse implements Serializable{
private static final long serialVersionUID = -2824767225275894898L;
#Autowired
private VZProperties properties;
public VZNFCTagResponse(List<VZNFCTagAction> tagList){
this.tags = tagList;
}
/*...*/
#JsonProperty
public String apiVersion(){
return this.properties.getApiVersion();
}
}
And after having checked to get it running via injecting Environment, the property isn't there, either.

Your class VZNFCTagResponse is not registered as Spring Beans.
Annotate it as #Component and use DI for inject him.

The only way to avoid making it into a component and still benefit from DI is to mark it #Configurable and enable load-time weaving. Can't you just inject it into the component that creates VZNFCTagResponse and pass the version as a constructor parameter?

Related

Injection using #Autowired not Working in #Webservice class

i'm trying to inject services in Web service Class like this
package com.mobinets.web.nep.backend.soapControllers;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import com.mobinets.web.nep.backend.data.entity.Router;
import com.mobinets.web.nep.backend.data.entity.Version;
import com.mobinets.web.nep.backend.services.RouterService;
import com.mobinets.web.nep.backend.services.VersionService;
#Service
#WebService
public class RouterSoapService extends SpringBeanAutowiringSupport{
#Autowired
private RouterService routerService;
#Autowired
private VersionService versionService;
#WebMethod
public String getRouter(#WebParam int objectId, #WebParam String versionName) {
Version version = versionService.findByName(versionName);
Router router = routerService.findByObjectIdAndVersion(objectId, version.getId());
return router.getName();
}
}
I extended the class from SpringBeanAutowiringSupport and add #Service annotation,
it keeps giving me null on versionService and routerService,
am I missing something ?
Only reason I can think of would be if either of the services
are missing one of the #Component stereotypes (you say they both have #Service
so this should be fine) or
if they rely on any other components which aren't autowired for example if
either has a repository which has been instantiated with the new keyword
they would be excluded from autowiring

Spring Boot #Autowired object - Nullpointer Exception [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 3 years ago.
I am developing a spring boot application to send sms notification. This is my class for the purpose.
package org.otp.services;
import org.otp.Configurations;
import com.mashape.unirest.http.HttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
#Component
public class SmsService
{
private static final Logger LOG = LoggerFactory.getLogger(SmsService.class);
public String send(String mobile, String msg)
{
//Code
}
}
And this is the class which uses the above class for sending notification.
package org.otp.controllers;
import org.otp.Constants;
import org.otp.services.EmailService;
import org.otp.services.SmsService;
import org.otp.dto.MessageRequest;
import org.otp.dto.MessageResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
#Component
public class MessageController {
private static final Logger LOG = LoggerFactory.getLogger(MessageController.class);
#Autowired
SmsService smsService;
public void sendMessageToAlert(#RequestBody MessageRequest messageRequest)
{
String smsStatus = "FAIL";
MessageResponse messageResponse = new MessageResponse();
//1. Nullpointer
smsStatus = smsService.send(messageRequest.getMobileNo(),messageRequest.getMessage());
}
}
Main Class
package org.otp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
#SpringBootApplication
#EnableAsync
public class OtpServiceApplication implements ApplicationRunner
{
public static void main(String[] args) {
SpringApplication.run(OtpServiceApplication.class, args);
}
}
Problem is, I get a nullpointer exception in the (1) stating that my SmsService object is null. And my main class is in package org.otp so the two classes here falls under sub package so no need of component scan.
Therefore I am confused what to do to solve this. I have tried many answers here like adding a #Component annotation and #ComponentScan in main class but nothing works. Could someone please point out my mistake here.
Thanks in advance.
If your #Autowired annotation is not working and throws NPE ,it means that spring fails to create an instance of the component class in the application context . Try to:
Verify that the classes are in class path for scanning and also check to ensure that all auto-wired classes have the annotation #Component to enable them to be picked up during class path scanning.
Check the spring boot start up logs to verify if there are any errors
during bean creation.
Check to ensure all related classes used in the service layer are auto-wired properly and that the injected classes are annotated with #Component .
For further help please share the main application class along with your project structure.
Since you are using springboot , it is preferable to use the sprinboot stereotype annotations instead of the #Component annotation, if you are building a standard springboot web application.
#Service : for the service layer.
#Controller : for the controller layer . Also,DispatcherServlet will look for #RequestMapping on classes which are annotated using #Controller but not with #Component.
In Springboot application's main class add following annotation
#SpringBootApplication
#ComponentScan(
basePackages = {"org.otp.*"}
)
public class YourSpringMainClass{
public static void main(String[] args) {
SpringApplication.run(YourSpringMainClass.class, args);
}
}
While using annotations we should configured with #ComponentScan annotation to tell Spring the packages to scan for annotated components. This should be used in mail class(Which class wants to load first) in your case you are working with spring boot so you should use this annotation in Springboot application's main class. Like below
#SpringBootApplication
#ComponentScan(
basePackages = {"org.otp.*"}
)
public class YourSpringMainClass{
public static void main(String[] args) {
SpringApplication.run(YourSpringMainClass.class, args);
}
}

How assign a a value from application.properties to a #Qualifier

I would like to assign a value with the name of the #Service from application.properties tu |#Qualifier . I tried but it doesn't work .
In fact i have two services which implement the same interface and i would like to change the service from application.properties
Someone has any idea how to do this?
this is my code
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class Controler {
#Qualifier("${service.name}")
#Autowired
private InterfaceTest interfaceTest;
#GetMapping("/test")
public String test(){
return interfaceTest.test();
}
}
Thank you very much for your help
I think you can do that in the constructor of this controller by using Environment and ApplicationContext beans.
Just remove Autowired annotation from fields and accept other parameters through constructor as well.
public Controller(Environment environment, ApplicationContext applicationContext) {
String serviceName = environment.getProperty("service.name");
this.interfaceTest = applicationContext.getBean(serviceName, InterfaceTest.class);
}
Those bean qualifiers and other annotations of spring just except literals as far as I know.
Hope this helps.

Application creates multiple CDI-Beans by mistake

i'm absolutely baffled. I have a standard, old school EJB-CDI-JSF-Hibernate JavaEE Application, running on a JBoss AS 7.1. Furthermore my structure is an absolut standard structure. I have JSF-Sites, which access my CDI Beans. The CDI Beans are holding a reference to one of my entities, the EJBs are used as DAOs. One of my beans is this CommissionController. It works absolutely fine. Only one instance is created for one user.
package controller;
import java.io.Serializable;
import java.util.Date;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import lombok.Data;
import lombok.extern.java.Log;
import entities.Commission;
#SessionScoped
#Data
#Log
#Named
public class CommissionController implements Serializable {
private static final long serialVersionUID = -8452887234021054225L;
#Inject
private UserController userController;
#Inject
private CartController cartController;
private Commission commission;
#PostConstruct
public void init() {
commission = new Commission();
log.info("new CommissionController instance");
}
public void makeNewCommission() {
commission.setCart(cartController.getCart());
commission.setOrderDate(new Date());
commission.setOrderer(userController.getUser());
cartController.clearCart();
log.info(commission.toString());
}
}
Now i have a different bean, but it think it's the excact same structure:
package controller;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import lombok.Data;
import lombok.extern.java.Log;
import entities.Article;
import entities.Cart;
#SessionScoped
#Data
#Log
#Named
public class CartController implements Serializable {
private static final long serialVersionUID = 649140288918816488L;
#Inject
private UserController userController;
#Inject
private ArticleController articleController;
private Cart cart;
public void addToCart(Article article) {
cart.getArticleList().add(article);
cart.setSum(cart.getSum() + article.getPrice());
}
public void clearCart() {
cart.getArticleList().clear();
cart.setSum(0.0);
}
#PreDestroy
public void destroy() {
log.info("bean destroyed");
}
#PostConstruct
public void init() {
cart = new Cart();
log.info("new CartController instance");
}
public void removeFromCart(Article article) {
cart.getArticleList().remove(article);
cart.setSum(cart.getSum() - article.getPrice());
}
}
I can't explain it to myself, but the second bean is instanciated again and again and I can't store anything in it, because it get always a reference to another bean.
Please, help me to bring light in this mystery. If you need additional information, I would love to give it to you. Maybe, I have a big lack of understanding but for now, I can't help myself.
Gimby gave me the answer to this question. In fact, JBoss AS 7.1.0 Community Edition is outdated. With WildFly 8.0.0 Final, everything worked perfectly fine. So, if you're working with the fantastic possibilities of CDI, try WildFly instead of JBoss AS 7.1.0 Final Community.

Java Spring Framework jmx managed annotation #ManagedAttribute not showing method in MBeanServerConnection/Jconsole/Visual vm/bean list

Ive Added Spring annotation's to my code
but when connecting via visual vm the method "myExample()" isn't showing in the JMX bean list
My code :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component;
#Component
#ManagedResource
public class MyClass {
#Autowired
private Example exampleService;
#ManagedAttribute
public String myExample() {
return exampleService.getSomething().toString();
}
}
any idea why this is happening ?
You should use #ManagedOperation instead. #ManagedAttribute is for a getter / setter methods only.

Categories