I am trying to autowire a service which is a proxy into a static class. Spring is not cooperating and it's not giving any indication of whats wrong.
I can only see:
Method threw 'org.springframework.beans.factory.BeanCreationException' exception. Cannot evaluate com.domain.services.SessionService$$EnhancerBySpringCGLIB$$f94406f3.toString()
in the debugger when I try to evaluate the variable.
I have a utility class for my controllers:
public class ControllerUtil {
private static SessionService sessionService;
public ControllerUtil(SessionService sessionService) {
this.sessionService = sessionService;
}
At application startup I try to add the sessionService to the static class. The session service is in session scope so I am trying to add the proxy here.
#Configuration
public class BeanConfig {
#Autowired
SessionService sessionService;
#PostConstruct
private void initStaticClasses() {
/*
* Need to add proxy to controller utils
* */
new ControllerUtil(sessionService);
}
Finally my SessionService class:
#Service
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionService {
#Autowired
BusinessDAO businessDAO;
Business business = businessDAO.getBusinessById("1");
public SessionService() {
System.out.println("New session service");
}
I am just trying to hardcode in the Business for dev purposes.
Spring must be failing somewhere but I'm not getting anything back in the logs and debugging isn't really helping.
Can anyone advise what I've done wrong?
Thanks
Add this line in your web app initializer if you are using java configuration.
servletContext.addListener(new RequestContextListener());
If you are using spring xml configuration add following in web.xml
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
Related
For example, what if several resource endpoints need access to some message bus to handle requests? Surely there is some way to register a singleton service class and inject it into the resources when the service class itself is NOT a resource but used by the resources.
All of the examples I've seen with providers or custom HK2 bindings refer to resources.
The closest thing I found to what I'm looking for was with this question:
Trouble creating a simple singleton class in Jersey 2 using built-in Jersey dependency injection
What is the best JAX-RS/Jersey way of doing this?
Note that the programmatic way would be most useful, I'm not using an xml file to configure the server.
If your platform supports EJB, you could use the #Singleton EJB (javax.ejb package, not javax.inject), and inject it on your resources with the #EJB annotation. Singleton EJB have also outofthebox concurrency access control.
On plain Jersey, you can use CDI application context. Declare the service class with an #ApplicationScoped annotation and inject it on your resources with #Inject. CDI will only instantiate one bean.
If you cannot annotate the service class, you can create a method that provides your service implementation an annotate it with #Produces and #ApplicationScoped.
#Produces
#ApplicationScoped
public MyService produceService() {
// instantiate your service client
}
And then use it on your resources, with:
#Inject
private MyService
Answer credit goes to #areus the answer provided here.
However, I'm providing my own answer so that I can share the code.
The Service Bean
#Singleton
public final class MyServiceBean
{
private static final AtomicInteger INSTANCES = new AtomicInteger();
private final AtomicInteger calls = new AtomicInteger();
public MyServiceBean()
{
INSTANCES.incrementAndGet();
}
public String getMessage()
{
return String.format("MyServiceBean{INSTANCES=%d, CALLED=%d}", INSTANCES.get(), calls.incrementAndGet());
}
}
The Resource Class
#Path("/messages")
public final class MyResource
{
#Inject
private MyServiceBean bean;
#GET
#Produces(MediaType.TEXT_PLAIN)
public Response handle()
{
return Response.ok(this.bean.getMessage())
.type(MediaType.TEXT_PLAIN_TYPE)
.build();
}
}
HK2 Binder
public final class MyServiceBeanBinder extends AbstractBinder
{
#Override
protected void configure()
{
bind(MyServiceBean.class).to(MyServiceBean.class).in(Singleton.class);
}
}
Then just register the binder and the resource like so:
final ResourceConfig config = new ResourceConfig();
config.register(MyResource.class);
config.register(new MyServiceBeanBinder());
Starting the server and hitting the resource multiple times yields:
MyServiceBean{INSTANCES=1, CALLED=1}
MyServiceBean{INSTANCES=1, CALLED=2}
MyServiceBean{INSTANCES=1, CALLED=3}
MyServiceBean{INSTANCES=1, CALLED=4}
MyServiceBean{INSTANCES=1, CALLED=5}
have have these two apps which actually do the same (if I am correct)
#SpringBootApplication
public class DemoApplication {
#Autowired
HelloWorld helloWorld;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
public CommandLineRunner run() {
helloWorld.setMessage("wow");
return (load) -> {
helloWorld.getMessage();
};
}
}
and
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new
ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}
both uses
#Component
public class HelloWorld {
private String message;
public void setMessage(String message) {
this.message = message;
}
public void getMessage() {
System.out.println("Your Message : " + message);
}
}
The only difference at the helloWord obj is, that if I use the MainApp-class in my program, then the helloWorld class doesn't need the #Component annotation.
My Question:
If I am correct the SpringBoot annotation makes it unnecessary to define a ClassPathXMLApplicationContext. #Autowire does that for me.
I am now interested if I AutoWire lets say 100 objects at the beginning, all these objects are now in the IoC container correct?
If so: Is not possible to just hand out that container in a CTOR of another class and have access to all saved objects there like:
(HelloWorld) context.getBean("helloWorld"); or
(someRandomClass) context.getBean("someRandomClass")
public CTOR(IOCContainer container) {
this.container = container;
}
Instead of that implementation
public CTOR(HelloWorld helloWorld, SomeRandomClass someRandomClass) {
this.helloWorld = helloWorld;
this.someRandomClass = someRandomClass;
}
And if that is possible, how can I do that?
(There is no use case/task behind my question, i am just interested if that is possible)
The XML'ish way of configuration where you define your bean and wiring via
<bean ... etc. pp.
can be completely replaced by either using
#Component
public class MyClass ....
or by
#Bean
public MyClass myClass() {return new MyClass();}
definition in a configuration class. Both ways place the entity in the IoC container of Spring.
The #Autowire just informs the IoC container of Spring that you would like to have a bean fulfilling the contract of the entity marked with #Autowire injected into this place.
In order to get access to the container you just need to inject the ApplicationContext where you would like to have it.
There are two ways of creating beans in Spring. One is through XML config and the other is through annotation config. Annotation config is the preferred approach as it has lot of advantages over xml config.
Spring boot doesnt have any thing to do with annotation or xml config. Its just a easy way to boot spring application. #Component creates the object of the annotated bean in the application context. #Import or #ImportResource are the annotations used to load the configs from Annotations or through XML configs in Spring boot. With Spring boot u need not create ClassPathXMlCOntext or AnnotationContext objects, but its created internally by spring boot.
#Autowired is a way of getting the beans into any object by injecting rather than tight coupling to the code. Spring container(Application context) do this job of injecting. Just autowiring any class wont create the objects in Spring context. Its just an indication for the Spring context to set the object in the Application context here. You need to create them explicitly inside a xml config/ or annotations like #Component #Service others.
There is no need of hand out of container anywhere. U can just #Autowire ApplicationContext context; in any other spring bean object. With which you can call getBean(YourBean.class) to get that bean.
at the moment we use Spring 4 and have a Java class loading all of our xml-config files:
Root: Basic Framework
Child: Project Application Services
Child: Project Application Workflow
Child: Framework Controller
Child: CXF Webapplication Context
Every child knows the beans of it's parent and everythings works fine. Now I have to use an IBM EJB on an Websphere Application Server for communication with legacy systems. This EJB gets called and now I want to use our Spring Context to get some services.
The EJB is defined as
#Stateless(mappedName = "ejb/LegacyRocks")
#RemoteHome(com.ibm.websphere.ola.ExecuteHome.class)
public class WolaUseCaseOne {...}
I have alreade read about the SpringBeanAutowiringInterceptor, but I do not get the point. I do not a a simple xml-file to get loaded, so can anybody provide me another way the autowire mit Spring Beans inside the EJB ?
PS:
I have also found this post (http://www.schakko.de/2013/10/11/sharing-the-spring-application-context-from-a-war-with-ejbs/), but we do not use JSF and it does not help me
I have already read, there is no way to inject the complete context, because we have a Webapplication Context, and there is not such a Web Context inside EJB... ?
you need to create ejb as per following
#Local
public interface TestManager {
boolean isValid();
}
#Stateless(name = "java:global/TestManagerImpl", mappedName = "java:global/TestManagerImpl")
#EJB(name = "java:global/TestManagerImpl", beanInterface = TestManager.class)
public class TestManagerImpl implements TestManager {
#PostConstruct
public void ejbCreate() {
}
#PreDestroy
public void ejbDestroy() {
}
#Override
public boolean isValid(){
//your code
}
}
and you need to implement spring service class with
#Service(value = "testServiceImpl")
public class TestServiceImpl {
#EJB(name = "java:global/TestManagerImpl", mappedName = "java:global/TestManagerImpl")
private TestManager testManager;
#Override
public boolean isValid(){
retrun testManager.isValid();
}
}
Edited
call ejb to spring service method
#Stateless
#Interceptors(SpringBeanAutowiringInterceptor.class)
public class TestManagerImpl implements TestManager {
// automatically injected with a matching Spring bean
#Autowired
private TestService testService ;
// for business method, delegate to POJO service impl.
public String myFacadeMethod(...) {
return testService.myMethod(...);
}
...
}
Hope it work for you!!
In a spring application, we write like this to get a bean through manually loading spring application context.
ApplicationContext context = new ClassPathXmlApplicationContext("path/to/applicationContext.xml");
JobLauncher launcher=(JobLauncher)context.getBean("launcher");
How to do the similar thing in spring boot ?
Being a newbie...need help
#SpringBootApplication
public class Application {
public static void main(String[] args) throws Exception {
ApplicationContext app = SpringApplication.run(Application .class, args);//init the context
SomeClass myBean = app.getBean(SomeClass.class);//get the bean by type
}
#Bean // this method is the equivalent of the <bean/> tag in xml
public SomeClass getBean(){
return new SomeClass();
}
#Bean
public MyUtilClass myUtil(SomeClass sc){
MyUtilClass uc = new MyUtilClass();
uc.setSomeClassProp(sc);
return uc;
}
}
You can also your xml file to declare the beans instead of the java config, just use #ImportResource({"classpath*:applicationContext.xml"})
Edit: To answer the comment: Make the util class a spring bean(using #Component annotation and component scan or the same as SomeClass shown above) and then you can #Autowire the bean you like. Then when you want to use the Util class just get it from the context.
I'm using Jersey 2 and Spring, and I'm trying to initialize my Jersey application (i.e. the class derived from ResourceConfig) with parameters from the Spring context.
Background: I have a single Jersey application that I build (i.e. a single WAR) and I deploy it across a server cluster with different Spring configurations on different servers to enable or disable different parts of the server, e.g. some of the servers have /search resources turned on, etc. This was really easy in Jersey 1.0: I just put,
<context:component-scan base-package="com.mycompany.resources.search"/>
in a Spring config to have Jersey scan that particular package and enable the JAX-RS resource providers in it.
Now in Jersey 2.0 the Spring <context:component-scan ... /> doesn't work, so resources have to be programmatically registered in a startup class derived from ResourceConfig:
public class MyApplication extends ResourceConfig {
public MyApplication() {
packages("com.mycompany.resources.search");
}
}
So far so good, but I need to conditionally scan that package, and I can't figure out how to get any Spring configuration into the MyApplication class. I thought that constructor injection might work:
public class MyApplication extends ResourceConfig {
#Autowired
public MyApplication(#Qualifier("my-config") MyConfiguration myConfiguration) {
if (myConfiguration.isEnabled()) {
packages("com.mycompany.resources.search");
}
}
}
However HK2 complains that it can't find a default constructor to use... so this indicates to me that DI is in play in the construction of this class, but that the DI isn't using Spring.
Similarly, using the the Spring bean lifecycle doesn't work:
public class MyApplication extends ResourceConfig implements InitializingBean {
#Autowired
private MyConfiguration myConfiguration;
public MyApplication() {
}
#Override
public void afterPropertiesSet() throws Exception {
if (myConfiguration.isEnabled()) {
packages("com.mycompany.resources.search");
}
}
}
(The afterPropertiesSet method isn't called.)
So now I'm stuck: is there any way to configure a Jersey ResourceConfig application object using Spring?
UPDATE:
I accepted #JohnR's answer below but I'll also include my eventual solution which I think is a bit cleaner. #JohnR's answer was to have the object initialized twice: first by Spring and then by Jersey/HK2. When Spring initializes the object you cache the dependencies in a static member, and then when Jersey/HK2 initializes it later you can retrieve the dependencies.
I ended up doing this:
public class MyApplication extends ResourceConfig {
public MyApplication() {
ApplicationContext rootCtx = ContextLoader.getCurrentWebApplicationContext();
MyConfiguration myConfiguration = rootCtx.getBean(MyConfiguration.class);
if (myConfiguration.isEnabled()) {
packages("com.mycompany.resources.whatever");
}
}
}
Rather than having the object initialized twice, we let Jersey/HK2 initialize it but then we retrieve the dependencies from Spring.
Both solutions are vulnerable to timing: they both assume that Spring is initialized before Jersey/HK2.
Expanding on my previous comment:
Trying to extend ResourceConfig is dangerous if you don't know what you're doing. Jersey becomes unpredictable, and if you try to subclass it into an Abstract class, Jersey crashes.
Instead, the JAX-RS specification provides us with a very useful interface called Feature: It allows you to register any classes you want as if you were configuring your own application. Furthermore, you don't need to use the awkward AbstractBinder, you just specify what contracts you register your classes with.
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
// Don't use #Component here, we need to inject the Spring context manually.
public class MySpringFeature implements Feature {
#Context
private ServletContext servletContext;
private ApplicationContext applicationContext;
#Autowired
private MySecurityDAO mySecurityDAO;
#Autowired
private MySpringResponseFilter myResponseFilter;
#Override
public boolean configure(FeatureContext context) {
if(this.servletContext == null) {
return false; // ERROR!
}
this.applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
if(this.applicationContext == null) {
return false; // ERROR!
}
// This is where the magic happens!
AutowireCapableBeanFactory bf = applicationContext.getAutowireCapableBeanFactory();
bf.autowireBean(this);
// From here you can get all the beans you need
// Now we take a Spring bean instance,
// and register it with its appropriate JAX-RS contract
context.register(myResponseFilter, ContainerResponseFilter.class);
// Or, we could do this instead:
SomeSecurityFilter mySecurityFilter = new SomeSecurityFilter();
mySecurityFilter.setSecurityDAO(mySecurityDAO);
context.register(mySegurityFilter, ContainerRequestFilter.class);
// Or even this:
SomeOtherSpringBean someOtherBean = applicationContext.getBean(SomeOtherSpringBean.class);
context.register(someOtherBean, SomeOtherJerseyContract.class);
// Success!
return true;
}
}
And in your ResourceConfig:
public class MyApplication extends ResourceConfig() {
public MyApplication() {
register(MySpringFeature.class);
}
}
Ta-da!
So now I'm stuck: is there any way to configure a Jersey
ResourceConfig application object using Spring?
I don't think you can configure Jersey to obtain your ResourceConfig from Spring as a Spring managed bean. It's a bit hackish, but you could do something like this. Note that you'll end up with two instance of your ResourceConfig: one managed by Spring and another by Jersey:
public class MyApplication extends ResourceConfig {
// static, available to all instances
private static MyConfiguration myConfiguration;
public MyApplication() {
// when Spring creates the first instance of MyApplication, myConfiguration
// will be null because the setter wasn't called yet
if (myConfiguration != null)
{
// second instance created by jersey... Spring will have autowired
// the first instance, and myConfiguration is static
if (myConfiguration.isEnabled())
packages("com.mycompany.resources.search");
}
}
#Autowired
public void setMyConfiguration(MyConfiguration config)
{
// instance level setter saves to a static variable to make it available for
// future instances (i.e. the one created by jersey)
MyApplication.myConfiguration = config;
}
}
Again, this is fairly hackish. You'll want to make sure Spring is initialized before Jersey and look closely at any threading issues that could occur during initialization.