I am trying to inject EJB into spring #Controller (spring boot), each time I receive null pointer on stetelessBean.tt();
#Local
public interface IStetelessBean {
void tt();
}
#Stateless
public class StetelesBean implements IStetelessBean {
public void tt(){
System.out.println("ttt");
}
}
#Controller
public class PersonService {
#EJB
IStetelessBean stetelessBean;
#RequestMapping("/test")
public void test(){
stetelessBean.tt();
}
}
Any idea? I am not sure what is wrong.
Spring can only inject beans, it knows about. By default, EJBs are not registered as Spring Beans. Also the #EJB annotation is not recognised by Spring. The only examples in the Spring documentation use XML configuration, so far i could not find any example for Java configuration. You might be better off with changing your EJB into a Spring component, if that's possible.
Related
I am trying to inject service in spring boot app. However I'm getting following error:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=RecommendationService,parent=RecommendationResourceImpl,qualifiers={},position=-1,optional=false,self=false,unqualified=null,1163111460)
Here is the code:
package com.example.test.recommendations.resources;
#Provider
public class RecommendationResourceImpl implements RecommendationResource {
#Inject
private RecommendationService recommendationService;
#Override
public List<Recommendation> get(String currency,
String entity) {
return recommendationService.getRecommendations(currency, entity));
}
}
Service interface
package com.example.test.recommendations.resources;
// imports
public interface RecommendationService {
List<Recommendation> getRecommendations(String currency, String entity);
Recommendation get(UUID uuid);
}
Service implementation
package com.example.test.recommendations.resources;
//imports
#Component
public class RecommendationServiceImpl implements RecommendationService{
#Override
public List<Recommendation> getRecommendations(String currency, String entity) {
return Collections.emptyList();
}
#Override
public Recommendation get(UUID uuid) {
return null;
}
}
What is correct way to inject services in spring boot applications?
I am using spring boot version 1.3.8 and Jersey version 2.25.1
From your stacktrace it is evident that the server cannot find the dependency bean to be injected.So initially check that the desired bean for the class is getting created during applciation start up.Verify that the service class is in the classpath for component scan to take place, otherwise include the package for scanning.
You are using the #Inject annotation instead of the spring #Autowired annotation to inject the beans.It will work fine but the first and most important difference between #Autowired and #Inject annotation is that the #Inject annotation is only available from Spring 3.0 onwards, so if you want to use annotation-driven dependency injection in Spring 2.5 then you have to use the #Autowired annotation.
Secondly, use the annotation #Service for the service layer rather than using the #Component annotation.
Indicates that an annotated class is a "Service", originally defined
by Domain-Driven Design (Evans, 2003) as "an operation offered as an
interface that stands alone in the model, with no encapsulated state."
May also indicate that a class is a "Business Service Facade" (in the
Core J2EE patterns sense), or something similar. This annotation is a
general-purpose stereotype and individual teams may narrow their
semantics and use as appropriate.
This annotation serves as a specialization of #Component, allowing for
implementation classes to be autodetected through classpath scanning.
#Service
public class RecommendationServiceImpl implements RecommendationService{
#Override
public List<Recommendation> getRecommendations(String currency, String entity) {
return Collections.emptyList();
}
#Override
public Recommendation get(UUID uuid) {
return null;
}
}
I am not an expert on using jersey with springboot , so i do not know if any configurations are causing this issue.
Maybe this thread might be of help to you more:
Dependency injection with Jersey 2.0
You probably never registered your Service with the DI-container. You can do that in your ResourceConfig, which you probably have since you are using jersey:
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(new org.glassfish.hk2.utilities.binding.AbstractBinder() {
#Override
protected void configure() {
bind(RecommendationServiceImpl.class).to(RecommendationService.class).in(Singleton.class);
}
});
packages("com.example.test.recommendations.resources");
}
}
I am using hk2 without spring, so I usually annotate my interfaces with org.jvnet.hk2.annotations.Contract and the implementations with org.jvnet.hk2.annotations.Service. (note: not the spring #Service annotation), so I recommend trying that as well.
Spring docs says that currently interface DI is not possible. See here: http://www.springbyexample.org/examples/core-concepts-dependency-injection-to-the-rescue.html
I've just started working with Spring boot and I made a simple webapp where I've used DI using interfaces. I can't find the reason on web. Why Spring Boot has this feature while Spring doesn't have!
Please help me in understanding the concept.
Thanks.
Edit
Dao Imple.
#Repository
public class AbcDaoImpl implements AbcDaoInt{
#Autowired
JdbcTemplate jdbc;
#Override
public int selectABC(String user, String password){
// some db query
}
Dao Interface
#Component
public interface AbcDaoInt{
int selectABC(String user, String password);
}
Service
#Service
public class adapter {
#Autowired
AbcDaoInt abcDao;
public Map<String, Object> abc(String user, String password) {
try{
int abcId = abcDao.selectABC(user, pwd);
}
}
There is no difference between spring and spring-boot regarding DI.
It is possible to use an interface for a field and to inject an implementation into that field.
I do not understand what the linked page means by
Interface Injection - This is not implemented in Spring currently
it seems to b wrong our outdated.
what exactly are you gonna do with injecting an interface . isn't interfaces are supposed to be implemented by a java class so whenever you are injecting a interface that means some class implementing the interface should be injected.
this is how you should do it, you have to enable component scan on the package where these classes are present then enable annotaions in order to use annotations.
<context:component-scan base-package="" />
<mvc:annotation-driven>
public interface singleInterface{
void someMethod();
}
#Component(value="b")
class B implements singleInterface{
public void someMethod(){
System.out.println(“from b class”);
}
}
#Component(value=“a”)
class A implements singleInterface{
public void someMethod(){
System.out.println(“from A class”);
}
}
//injecting
#Autowire
#Qualifier("b")
singleInterface bInterface;
bInterface.someMethod();//print from b class.
#Autowire
#Qualifier("a")
singleInterface aInterface;
aInterface.someMethod();//print from a class.
this works on spring boot and on spring mvc you dont have to enable component scan in spring boot.
I have 3 classes which are found in different packages in a spring boot application as follows:
Why does #Autowired work in certain classes only?Anything I am doing wrong?
#Configuration
public class Configurations{
#Autowired
Prop prop; //works fine
#Bean
//other bean definitions
}
#Component
public class Prop{
public void method(){};
}
public class User{
#Autowired
Prop prop; //does not work, null
public void doWork(){
prop.method();
}
}
I have also tried the #PostConstruct, but same result
public class User{
#Autowired
Prop prop; //does not work, null
#PostConstruct
public void doWork(){
prop.method();
}
}
The #Autowired annotation works only if Spring detects that the class itself should be a Spring bean.
In your first example you annotated Configurations with the #Configuration annotation. Your User class on the other hand does not have an annotation indicating that it should be a Spring bean.
There are various annotations (with different meanings) to make your class being picked up by the Spring container, some examples are #Service, #Component, #Controller, #Configuration, ... . However, this only works if your class is in a package that is being scanned by the Spring container. With Spring boot, the easiest way to guarantee that is by putting your User class in a (sub)package of your main class (the class annotated with #SpringBootApplication).
You can also manually create your bean by writing the following method in your Configurations:
#Bean
public User user() {
return new User();
}
In this case you don't have to annotate your User class, nor do you have to make sure that it is in a package that is being scanned.
I have the following spring configuration:
<context:component-scan base-package="uk.co.mysite.googlecontactsync.aop"/>
<bean name="simpleEmailSender" class="uk.co.mysite.util.email.simple.SimpleEmailSenderImplementation"/>
<aop:aspectj-autoproxy/>
Then I have an aspect:
#Aspect
public class SyncLoggingAspect {
#Autowired
private SimpleEmailSender simpleEmailSender
#AfterReturning(value="execution(* uk.co.mysite.datasync.polling.Poller+.doPoll())", returning="pusher")
public void afterPoll(Pusher pusher) {
simpleEmailSender.send(new PusherEmail(pusher));
}
}
This aspect works (I can hit a breakpoint on afterPoll) but simpleEmailSender is null. Unfortunately I cannot find clear documentation on why this is. (For the record, my simpleEmailSender bean exists and is correctly wired into other classes) The following things confuse me:
Is context:component-scan supposed to be picking up #Aspect? If it is then surely it would be a spring managed bean, thus autowired should work?
If context:component-scan isn't for creating aspects, how is my aspect being created? I thought aop:aspectj-autoproxy just creates a beanPostProcessor to proxy my #Aspect class? How would it do this if it isn't a spring managed bean?
Obviously you can tell I don't have an understanding of how things should be working from the ground up.
The aspect is a singleton object and is created outside the Spring container. A solution with XML configuration is to use Spring's factory method to retrieve the aspect.
<bean id="syncLoggingAspect" class="uk.co.demo.SyncLoggingAspect"
factory-method="aspectOf" />
With this configuration the aspect will be treated as any other Spring bean and the autowiring will work as normal.
You have to use the factory-method also on Enum objects and other objects without a constructor or objects that are created outside the Spring container.
For Spring Boot to use #Autowired with AspectJ I have found the following method.
In configuration class add your aspect:
#Configuration
#ComponentScan("com.kirillch.eqrul")
public class AspectConfig {
#Bean
public EmailAspect theAspect() {
EmailAspect aspect = Aspects.aspectOf(EmailAspect.class);
return aspect;
}
}
Then you can successfully autowire your services in your aspect class:
#Aspect
public class EmailAspect {
#Autowired
EmailService emailService;
Another option is to add #Configurable to your aspect class instead of messing around with XML.
Configuring #Autowired with java config only (so no XML based configuration) requires a bit of extra work than just adding #Configuration to the class, as it also needs the aspectOf method.
What worked for me was creating a new class:
#Component
public class SpringApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
And then use that in you aspect in conjunction with using #DependsOn #Configured and #Autowired:
#DependsOn("springApplicationContextHolder")
#Configuration
#Aspect
public class SomeAspect {
#Autowired
private SomeBean someBean;
public static SomeAspect aspectOf() {
return SpringApplicationContextHolder.getApplicationContext().getBean(SomeAspect.class);
}
The #DependsOn is needed because spring can't determine the dependency because the bean is used staticly.
I dont have 50 rep to comment on a question so here is another answer relating to #
Jitendra Vispute answer.
The official Spring doc mentions:
You may register aspect classes as regular beans in your Spring XML configuration, or autodetect them through classpath scanning - just like any other Spring-managed bean. However, note that the #Aspect annotation is not sufficient for autodetection in the classpath: For that purpose, you need to add a separate #Component annotation (or alternatively a custom stereotype annotation that qualifies, as per the rules of Spring’s component scanner).Source: Spring '4.1.7.Release' documentation.
This would mean that adding a #Component annotation and adding the #ComponentScan on your Configuration would make #Jitendra Vispute's example work. For the spring boot aop sample it worked, though I did not mess around with context refreshing.Spring boot aop sample:
Application:
package sample.aop;
#SpringBootApplication
public class SampleAopApplication implements CommandLineRunner {
// Simple example shows how an application can spy on itself with AOP
#Autowired
private HelloWorldService helloWorldService;
#Override
public void run(String... args) {
System.out.println(this.helloWorldService.getHelloMessage());
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleAopApplication.class, args);
}
}
The application should also run as plain Spring Framework application with the following annotations instead of #SpringBootApplication:
#Configuration
#EnableAspectJAutoProxy
#ComponentScan
and an AnnotationConfigApplicationContext instead of SpringApplication.
Service:
package sample.aop.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class HelloWorldService {
#Value("${name:World}")
private String name;
public String getHelloMessage() {
return "Hello " + this.name;
}
}
Monitor Aspect:
package sample.aop.monitor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class ServiceMonitor {
#AfterReturning("execution(* sample..*Service.*(..))")
public void logServiceAccess(JoinPoint joinPoint) {
System.out.println("Completed: " + joinPoint);
}
}
This blog post explains it really well. Due to the fact that aspect singleton is created outside spring container you'd need to use factory-method=”aspectOf” that is only available after it is woven in by AspectJ ( not Spring AOP ) :
Notice factory-method=”aspectOf” that tells Spring to use a real
AspectJ ( not Spring AOP ) aspect to create this bean. So that after
the aspect is woven in it has an
“aspectOf” method.
So that :
No matching factory method found: factory method 'aspectOf()' - That
would mean that the aspect was not woven by AspectJ weaver.
From my experience with spring 3.1, if I don't use #Autowired but traditional setter for dependency injection, it gets injected and works as expected without aspectJ weaver. Although I'm encountering problems with the aspect being singleton... It results in 'perthis' instantiation model.
.
Add #Component to aspect class and your dependencies should get injected automatically.
and add context:component-scan for package where your aspect is in spring context file.
#Component
#Aspect
public class SomeAspect {
/* following dependency should get injected */
#Autowired
SomeTask someTask;
/* rest of code */
}
Use compile time weaving, see for plugin example at: https://github.com/avner-levy/minimal_spring_hibernate_maven_setup/blob/master/pom.xml
The following combination of annotation and Spring config works for me thanks to notes above by Tobias/Willie/Eric:
Class:
package com.abc
#Configurable
#Aspect
public class MyAspect {
#Autowired
protected SomeType someAutoWiredField;
}
XML:
<context:spring-configured />
<context:component-scan base-package="com.abc" />
#Configurable(autowire = Autowire.BY_TYPE)
Add this annotation to your Aspectj class. Then it will be handled by Spring IOC.
For Spring Boot using #Autowired in #Aspect,
my way is using spring.factories configuration file
create a file named spring.factories in src/main/resources
the file content is as following
org.springframework.boot.autoconfigure.EnableAutoConfiguration=pack.age.to.YourAspect,pack.age.to.YourDAO
I have this HTTP listener subclass
public class MigificSessionListener implements HttpSessionListener {
#Autowired
#Qualifier("notificationThread")
private NotificationThread notificationThread;
#Override
public void sessionDestroyed(HttpSessionEvent hse) {
// here notificationThread value is null
}
}
Value of notificationThread inside sessionDestroyed() is null.
How can i autowire sessionDestroyed inside this class ?
Your MigificSessionListener in not in your spring conext, spring even do not know it exists.
You can use WebApplicationContextUtils to get your spring context from ServletContext
WebApplicationContextUtils.getWebApplicationContext(sessionEvent.getSession().getServletContext())
You can enable Spring AOP with #EnableSpringConfigured and annotate your class with #Configurable. This let spring manage instances which are created outside the spring context with new. You will also need to enable either load-time weaving or compile-time weaving. This is documented in 9.8.1 Using AspectJ to dependency inject domain objects with Spring.
#Configuration
#EnableSpringConfigured
public class AppConfig {
}
#Configurable
public class MigificSessionListener implements HttpSessionListener {
#Autowired
#Qualifier("notificationThread")
private NotificationThread notificationThread;
//...
}
Convert your non-Spring managed class MigificSessionListener into a Spring-managed one by annotating it with #Configurable.
For this annotation to be recognised you need <context:spring-configured/> in your Spring XML config or #EnableSpringConfigured if you are using Spring Java config.
The #Autowired or injection of other dependencies will then succeed.