How to add POJO to Spring context to enable injecting dependencies? - java

I have a class that would otherwise be a very generic POJO but I would like to inject a dependency in it because I would like to avoid passing that dependency as a (constructor) parameter:
//no managed context annotation because it's a simple POJO
public class QueuedBatch {
//however, I would like to inject the context managed bean below
#Autowired
AsyncActionQueue asyncActionQueue;
Currently, no exception is thrown at deploy time but asyncActionQueue is null at runtime so I get a NullPointer when I hit the POJO.
How can I annotate my POJO to add it to the Spring managed context so that I can inject dependencies into it? AsyncActionQueue is a singleton and I would rather not be passing it to QueuedBatch as a (constructor) parameter.
This post is similar, except that I want to add my POJO into the managed context.

As the comments suggested you have 2 ways of dealing with this
Pass the AsyncActionQueue as a parameter in the constructor of QueuedBatch. This doesnt require Spring to know anything about QueuedBatch, but enforces the dependency to be provided when an instance of QueuedBatch is created.
Annotate the QueuedBatch class with #Component. And ensure that the package which contains QueuedBatch is included in the component scan when initializing the spring context. In this way, it becomes a spring managed bean allowing AsyncActionQueue to be autowired into it. You may change the scope of QueuedBatch component based on your requirement.

Related

Spring injects constructor arg while it's not passed in the xml

I'm working on an application that uses both XML and spring boot. There is a class that is not annotated as Service or Component, etc. Nor its constructor is annotated with #Autowired.
This class is defined in a xml as a bean and the args are defined as separate beans in the same xml, but one of the beans (although being defined in that xml) is not passed to this bean as constructor-arg. But the bean is still created, and it works.
I know since Spring 4.3 there is no need to annotate #Autowired the constructors of classes with with only one constructor. But this class is not annotated with Service or Component either.
How does Spring figure that missing constructor out?

How to tell if a class is Spring loaded in java?

I have been given a task to assign a property from .properties file to a non Spring bean class using #Value annotation. To do this, I created a method on a #Component annotated class and set the property into it, then called that method from the non Spring bean class. I thought this would work, however, still showing as null.
I was told this is because the #Component annotated class I used is not spring loaded. Question, how can I tell if a class is Spring loaded bean? I have been searching on google but can't find anything helpful aside from examples with #Component or #Configuration annotations. Thanks.
Spring Container is responsible for creating or managing beans. It all satisfy the dependencies by injecting them either through constructor or setter method. But in your case you want the #Value injection in your non spring bean which is really not possible as per my understanding. Because here the spring does not creating the object then how it satisfy the dependencies of it.
You have two options for this situation.
Either annotate class using #Component
Either read property file using Properties
https://www.mkyong.com/java/java-properties-file-examples/

Spring auto inject with constructor via code or annotations

Given having next classes:
XRepository with declared a constructor with 1 argument (simple one,
not autowired), it has some autowired fields.
XService that uses XRepository as autowired.
XProcessor uses XService as autowired.
So I have to init XProcessor on runtime for specific value that will be used in XRepository constructor. On different calls I will have different arguments, so the injection should be on runtime.
Any idea how to achieve that using code configuration or annotations?
Remember that Spring needs to inject all the constructor parameters of Spring managed beans.
I believe you have two options:
Parse your URL info in controller and pass it through parameters down to persistence layer. This would be my preferred mechanism. You can create special DTO for passing various information down and keep your method signatures concise.
Your situation can alos be solved with request scope bean. You will
create one bean like this:
#Component
#Scope("request")
public class {
private String urlPart;
}
And you would autowire this component into XProcessor and
XRepository. Each request to your application will create new
instance of XRequestContext and you will parse your info in
XProcessor and store it into XRequestContext.
In XRepository you will use instance of XRequestContext to
retrieve information you stored in XProcessor.
You can read about request scope in Spring docs. It is like
ThreadLocal per request thread.

Spring annotations and XML configuration

I was reading Spring 3.0 documentation and I came to the sentence -
Annotation injection is performed before XML injection, thus the latter configuration
will override the former for properties wired through both approaches.
Next the question came to my mind:
If I use an annotation in a bean (like #Service("myService")), now I am using the other bean and it uses "myService", and "myService" would be injected through XML configuration.
Would this work? I tried but it is giving me
BeanCreationException (Cannot resolve reference to bean 'myService' while setting bean property 'myService')
Later, I went through this question Wiring Spring bean through annotations and xml context, but in the solution it is told that "Just leave all your annotated fields unspecified, and they'll get injected auto-magically." (I didn't try out this solution)
But what if I want to specify all annotated fields, like I specified #Service annotation above?
Any suggestions??
I figured out the answer, it works very well. Actually I forgot to add tag in xml configuration. We need to add this tag in each config file i.e. if you have written config file for service layer beans, add tag for service layer annotated beans. Similar for dao and controller layers.
You need to autowire your constructor like below...
#Autowired(required=true)
public UserService(DataSource dataSource){
this.userDS = new UserDS(dataSource);
}
So, in the above code the DataSource will be injected in the UserService automatically.

Wicket #SpringBean doesn't create serializable proxy

#SpringBean
PDLocalizerLogic loc;
When using above I receive java.io.NotSerializableException. This is because loc is not serializable, but this shouldn't be problem because spring beans are a serializable proxies.
I'm using wicket-spring library, and as injector SpringComponentInjector, where wrapInProxies is by default set to true, so I think that proxies should be created, but they aren't.
On the page https://cwiki.apache.org/WICKET/spring.html#Spring-AnnotationbasedApproach is written:
Using annotation-based approach, you
should not worry about
serialization/deserialization of the
injected dependencies as this is
handled automatically, the
dependencies are represented by
serializable proxies
What am I doing wrong?
Do you know how the bean is being injected?
Through component initialization (i.e. a Component and being filled in by the SpringComponentInjector)
Some other object using InjectorHolder.getInjector().inject(this)?
Injected directly by spring (i.e. this is a spring bean where the property is being set by Spring configuration)
Cases 1 and 2 would use wicket-spring integration and would wrap the bean with a wicket proxy which is serializable.
Case 3 would only provide you whatever spring passes to you without wrapping.
First, make sure your bean is really proxied. By default spring does not create proxies.
Second, check your proxying strategy - whether it is proxy-target-class="true" or not. If it is false, (afaik) a reference to your object is stored in the invocation handler of the JDK proxy, and is attempted to be serialized.
So you'll need to make your class Serializable as well, if you need it to be.
Can you double check that the instantiation listener is added in your application class:
addComponentInstantiationListener(new SpringComponentInjector(this));
Also, this only works for fields in Wicket components, not arbitrary classes.
See also wicket #SpringBean can not create bean

Categories

Resources