I'm working in a spring application and I'm trying to use a service class which works perfectly but not inside a simple class.
I suppose that this has to be with bean injection?? or maybe to access spring application context??
What's the best approach to solve this?
Here's my class:
public class RequestDatosFactura
{
JSONObject request;
private Factura factura;
#Autowired
private BitacoraService bitacoraServ;
public RequestDatosFactura(String req) throws JSONException {
this.request = new JSONObject( req );
this.factura = crearFactura();
}
//methods inside class...
This simple class tries to autowired BitacoraService, but when I instantiate, say for example into a spring controller it does well but the BitacoraService is not working.
Any guide or help will be very appreciated
The solution here is to get the service injected in the controller then pass that instance to your regular class, something like:
#Controller
class YourController {
#Autowired
private BitacoraService bitacoraService;
public void someMethod() {
RequestDatosFactura requestDatosFactura = new RequestDatosFactura(bitacoraService);
// use "requestDatosFactura"
}
}
class RequestDatosFactura {
// ...
private final BitacoraService bitacoraService;
public RequestDatosFactura(final BitacoraService bitacoraService) {
this.bitacoraService = bitacoraService;
}
// ...
}
Related
I'm trying to create a simple Spring Boot Application, creating a GET using resttemplate.getForObject and instead of hard coding the url within the parameter, I want to create a string and leverage #Value to call the url from application.properties. I've checked videos and the board (#Value in Springboot returns null) and every time I run my JUnit test the endpoint is null. I was wondering if someone can take a look at my code and point out what am I doing incorrectly, why is #Value always null and what can I do to fix this?
#SpringBootApplication
public class NhlTeamsApplication {
public static void main(String[] args) {
SpringApplication.run(NhlTeamsApplication.class, args);
}
}
//my controller
public class NhlTeamsController {
#Autowired
private NhlTeamsService nhlTeamsService;
#RequestMapping(method = RequestMethod.GET, value = "/requestAllTeams")
public #ResponseBody String requestAllTeams() {
return nhlTeamsService.allTeamsService();
}
}
//my interface
#Component
public interface NhlTeamsService {
String allTeamsService();
}
//implementation
#Service
#Data
#Configuration
#PropertySource("classpath:application.properties")
public class NhlTeamsServiceImpl implements NhlTeamsService{
#Value("${nhl.endpoint}")
private String endpoint;
#Override
public String allTeamsService() {
RestTemplate restTemplate = new RestTemplate();
return restTemplate.getForObject(getEndpoint(), String.class);
}
}
//application.properties
nhl.endpoint=https://statsapi.web.nhl.com/api/v1/teams
//JUnitTest
#Test
public void nhlAllTeamsTest(){
NhlTeamsServiceImpl nhlTeamsService = new NhlTeamsServiceImpl();
System.out.println(nhlTeamsService.allTeamsService());
}
Am I missing any annotations? Any insight is greatly appreciated.
When you running tests that time you create a new object of NhlTeamsServiceImpl.
But in spring have spring container inside that at run time spring had to initialize that object with all variable & stored.
So when you create a new object it will initialize of spring container & in that it doesn't have to initialize all required thing as #value variable
so do one thing in test case class modified as follows,
class junit{
#Autowired
public NhlTeamsServiceImpl nhlTeamsServiceImpl;
//JUnitTest
#Test
public void nhlAllTeamsTest(){
//NhlTeamsServiceImpl nhlTeamsService = new NhlTeamsServiceImpl();
System.out.println(nhlTeamsService.allTeamsService());
}
}
So it will work.
Find below the working snap.
& same working code add here https://github.com/MaheshMore4321/RunTestCases
I need to create objects with user defined data at runtime.TO do that i have used
google guice assisted inject.But when i run my test it throws null pointer exception.Please let me know where i made the mistake.
IArtifacts Interface
public interface IArtifacts {
MavenMetaDataXMLDTO getArtifactsVersions();
}
ArtifactsService.java
public class ArtifactsService implements IArtifacts {
private ProductProfile productProfile;
#Inject
public ArtifactsService(#Assisted ProductProfile productProfile){
System.out.println(productProfile.getArtifactManagementURL());
this.productProfile=productProfile;
}
#Override
public MavenMetaDataXMLDTO getArtifactsVersions() {
System.out.println(productProfile.getArtifactManagementURL());
return null;
}
}
ArtifactsFactory Interface
public interface ArtifactsFactory {
IArtifacts create(ProductProfile productProfile);
}
Module Class
#Override
protected void configure() {
install(new FactoryModuleBuilder().implement(IArtifacts.class,ArtifactsService.class).build(ArtifactsFactory.class));
}
TestArtifacts.java
public class TestArtifacts {
#Inject // this obj is null
private ArtifactsFactory artifactsFactory;
private IArtifacts s;
public TestArtifacts(){
}
public void getdata(){
//Pass custom data to factory
this.s=artifactsFactory.create(Products.QA.get());
System.out.println(s.getArtifactsVersions());
}
}
REST ENDPOINT
#GET
#Path("/test")
#Produces(MediaType.APPLICATION_JSON)
public String getartifacts(){
new TestArtifacts().getdata();
}
you created an Instance of the class TestArtifacts on your own in your Rest Endpoint class but all of your classes need to be created by the Guice Framework and not by you.
So how should the Guice Framework inject something into your class when you create them with new? You also need to inject the class TestArtifacts into your Rest Endpoint and your Rest Endpoint has to be created by Guice too.
Update:
Maybe this link will help you
https://sites.google.com/a/athaydes.com/renato-athaydes/posts/jersey_guice_rest_api
I was able to fix it adding following code snippet to below TestArtifacts.java class
TestArtifacts.java
private Injector injector=Guice.createInjector(new MYModule());//where implemented configuration
#Inject
private ArtifactsFactory artifactsFactory=injector.getInstance(ArtifactsFactory.class);
I have a Rest Controller in which I initialise a service like this :
class Config {
#Value(${"number.of.books"})
private final static String numberOfBooks;
}
class MyController {
private final Service myService = new ServiceImplementation(Config.numberOfBooks)
public ResponseEntity methodA() { ... }
}
The numberOfBooks field has a initialisation value but when it's passed in the ServiceImplementation constructor it comes null.
I'm thinking I'm missing something obvious over here.
What is the mistake and which would be the best practice to inject a value from a property file into a constructor?
I recommend you to directly inject numberOfBooks in your ServiceImplementation, as follows:
public class ServiceImplementation implements Service {
#Value("${number.of.books}")
private String numberOfBooks;
}
Otherwise use setter injection for static variables, as follows:
#Component
class Config {
public static String numberOfBooks;
#Value("${number.of.books}")
public void setNumberOfBooks(String numberOfBooks) {
numberOfBooks = numberOfBooks;
}
}
After studying a little I've found out that the dependency injection happens after the constructor has been called. This being said the approach used was to use Autowired on my services constructor.
class ServiceImplementation implements Service {
private final String numberOfBooks;
#Autowired
private ServiceImplementation(Config config) {
this.numberOfBooks = config.getNumberOfBooks();
}
}
In this way Spring creates the dependency tree and makes sure that Config is not null when injected.
I'm new to Spring so I'm just trying to understand how it works. I've developed a simple servletprojectusing spring to manage hibernate framework.
I have a service
#Service("service")
#Transactional
public class CdServiceImpl {
#Autowired
private HibernateUtility hibernateutility;
public int saveCd(CD cd) {
return hibernateutility.saveCd(cd);
}
public List getCd(String searchedCd) {
return hibernateutility.getCd(searchedCd);
}
public List getAllCd() {
return hibernateutility.getAllCd();
}
public void deleteCd(int id) {
hibernateutility.deleteCd(id);
}
public User getUser(String username, String password) {
return hibernateutility.getUser(username, password);
}
}
And then I use it in the servlet
context.scan("it.project");
context.refresh();
CdServiceImpl service = (CdServiceImpl) context.getBean("service");
context.register(ApplicationContextConfig.class);
context.refresh();
1) It works but I have two question. It is the right way to work?
2) I've tried to set a field in the servlet like:
#Autowired
private CdServiceImpl service
and then I remove the context.scan ecc part and it gave me nullpointerexception. Why?
Doing that I also defined a new bean
#Bean
public CdServiceImpl getCdServiceImpl() {
return new CdServiceImpl();
}
Why it doesn't work? I know that maybe this is a noob question but I'm tryingto figure out how spring works
Basically as soon as you start doing things like new **ApplicationContext you need to scratch your head, take 2 steps away from the keyboard and think if you really want to do this. In 99% of the cases this isn't what you want or at least should do.
Instead have the ContextLoaderListener load your configuration. Assuming you don't have a web.xml use the the AbstractContextLoaderInitializer base class.
public ApplicationInitializer extends AbstractContextLoaderInitializer {
protected WebApplicationContext createApplicationContext() {
return new AnnotationConfigWebApplicationContext(ApplicationContextConfig.class);
}
}
Note: As this is for bootstrapping your application you need to create the the context. You could also use AbstractAnnotationConfigDispatcherServletInitializer which eliminates this need, but also creates a DispatcherServlet which you don't need.
Now that your configuration is automatically loaded you can use the WebApplicationContextUtils to get the context to do the lookup. Do this in the init method of your servlet.
public class YourServlet extends GenericServlet {
private CdServiceImpl service;
public void init() throws ServletException {
ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
service = ctx.getBean(CdServiceImpl.class);
}
}
Now you initialize the bean once and don't need to handle anything anymore. You could also use #Autowired and manuallly have it injected.
public class YourServlet extends GenericServlet {
#Autowired
private CdServiceImpl service;
public void init() throws ServletException {
ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
ctx.getAutowireCapableBeanFactory().autowireBean(this);
}
}
I am newbie to Spring Framework.I have tried following example in spring.
#Path("/XZY")
#Service
#Transactional
public class XZY {
#Autowired
SampleDAO sampleDao;
#Autowired
TestDAO testDao;
#Autowired
XZYinterface xzyinterface;
#POST
#Produces("text/plain")
#Path("/checkservice")
public Response XZYservice(#FormParam("Code") String Code,
#FormParam("source") String source,
#FormParam("value") String value) {
//return xzyinterface.checkXYZService(Code,sourceName,source);
XZYinterface xyz = ServiceFactory.getXZY(999);
return xyz.checkXYZService(Code,sourceName,source);
}
}
The following code will use to create singleton object
public class Singleton {
private static sampleA sampleClassA=null;
private static SampleB sampleClassB=null;
public static XZYAbstract getXZY(long id){
if(id == 999){
if(sampleClass == null){
sampleClassA = new sampleA();
}
return sampleClass;
}
if(id == 9999){
sampleClassB = new sampleA();
}
return sampleClassB;
}
}
Interface
public interface XZYinterface {
Response XZYservice(String Code, String source,String value)
}
Abstract class and implements Interface
public class XZYAbstract implements XZYinterface {
public XZYAbstract(){
super();
}
#Autowired
SampleDAO sampleDao;
#Autowired
TestDAO testDao;
public Response checkXYZService(String Code,String source,String value){
String sample = sampleDao.getValue(code);
//..source code
}
}
The following class extends abstract class.
public class sampleA extends XZYAbstract {
//some methods.
}
If i run the application it throws following errors
SEVERE [com.sun.jersey.spi.container.ContainerResponse] The RuntimeException could not be mapped to a response, re-throwing to the HTTP container: java.lang.NullPointerException
at com.test.xyz.XZYAbstract.checkXYZService(XZYAbstract.java:112) [:]
at com.test.XYZ.XZYservice(XZY.java:140) [:]
If i call directly without singleton object, values are initialized properly using Auto wired (//return xzyinterface.checkXYZService(Code,sourceName,source);) and it's working fine.
Throw from singleton object, values(sampleDAo,testDao) are not initialized properly.
How to resolve this error?
The reason is quite trivial: it's because Spring is just a library, and not a change to the Java language. Spring doesn't instrument nor enhance constructors, so the only way to get initialized Spring bean is to get it from the Spring context.
If you call new Bean(), you becomes Bean instance untouched by Spring.
For the question how to use singleton bean: do nothing. Spring beans are Singletons by default. You can specify other scope via #org.springframework.beans.factory.config.Scope annotation. See for example #Scope("prototype") bean scope not creating new bean, how it works.