Inject #Context values into regular beans - java

Is it possible to inject #Context values into regular spring beans (not Jax-Rs resources or providers)?
JERSEY-469 would suggest it can be done, but when I view it in debugger the fields are null (I'm checking this well after creation, this is not a problem with InitializingBean, I can't get the field injected at all).
#Component
#Scope("prototype")
public final class TaskDO {
#Context private ResourceContext resourceContext;
#FormParam("xml") private String xml;
}

Related

Bean singleton, session creation and initialization

I don't know if it is the better way to implement my solution:
#Component
#Scope("singleton")
public class GetFromJson implements Serializable{
/**
*
*/
private static final long serialVersionUID = -8203722696439228358L;
Map<String, Map<String, ArrayList<String>>> jsonMap;
public Map<String, Map<String, ArrayList<String>>> getJsonMap() {
return jsonMap;
}
public void setJsonMap(Map<String, Map<String, ArrayList<String>>> jsonMap) {
this.jsonMap= jsonMap;
}
}
The class is Serializable because I get the content from a Json from a database and I map the content in an Object GetFromJson (I need do the query in database only one time). For this reason I need use the Object in all my APp, for this reason I think that I need use a Singleton
Somebody publish to me a library to get the JSON from database. the JSON object parse to Map<String, Map<String, ArrayList<String>>> for this reason I create my GetFromJson class.
Now I have many rest Service, in my rest services I need use my object: GetFromJson to get the content of jsonMap.
I have many questions.
With the annotation #Scope("singleton") I guarantee have the GetFromJson only one instance available in all my app?
Or what is the better way to have in Spring a singleton and session object available in my app?
To access to get the content of jsonMap of GetFromJson is enough use
#Autowired
private GetFromJson jsonObject;
Or how can I get my singleton class?
and in my rest method service use:
jsonObject.getJsonMap();
How can Initialize my singleton, because i am trying initialize my object with:
#Autowired
private GetFromJson jsonObject;
public methodToInitialize(){
jsonObject = methodLibraryFromDatabase(GetFromJson.class);
}
ANd the IDE tell to me that the field initialization is not used
I need the same logic, but with session Object, I think that if I understand the singleton implementation with my session object will be the same but only changing the anotation to: #Scope("session")
I think what OP is wants to initialize database based POJO once in application lifecycle and autowire it where needed.
Typically this is done by creating a bean (which are singletons unless otherwise specified) and autowiring it where needed.
This sample should get you started.
#Configuration // beans are declerated in #Configuration classes
public class GetJsonInitializer {
#Bean // singleton by default
public GetFromJson jsonMap(){
GetFromJson jsonObject = methodLibraryDatabase(GetFromJson.class);
return jsonOBject;
}
}
Now autowire GetFromJson in any Spring service/component etc.
#Service
public class SomeService {
#Autowired
private GetFromJson jsonMap;
}
Hope this helps!
a bean annotated with session scope is going to be bound to user's session life cycle, that is, for each user accessing your app, you'll have an instance of this class. If you want to guarantee only one instance of this bean in your application (at JVM level) you just need to remove the #Scope annotation. However, if you want to mix singletons with session scoped beans, then you should just let spring handle everything seamless for you, your session scope beans will only be destroyed when the user session ends.
The best way to handle initialization code in your bean is in a public method annotated with javax.annotation.PostConstruct
#PostConstruct
public void setUp() {
//initialization code
}
In order to handle a clean up code when a bean is going to be destroyed, you should make your class implement org.springframework.beans.factory.DisposableBean or add a method annotated with javax.annotation.PreDestroy
#PreDestroy
public void onDestroy() {
//clean up code
}
I hope this has helped you out!

How do I convert an object using ObjectMapper and inject dependencies into it

I am trying to convert Object to a concrete class using jackson ObjectMapper and to inject dependencies after I convert it.Here is the example:
public class SimpleClass{
private String parameter;
#JsonIgnore
private SomeService service;
/** getters and setters **/
public void doSomethingFromService(){
//call some methods from the service
}
}
After attempt to deserialize the object(value is map containing parameters) :
ObjectMapper om = new ObjectMapper();
om.convertValue(value,SimpleClass.class).doSomethingFromService();
-> result to a NullPointerException...
How to inject the service?
Can I get the service from the context and inject it by default constructor?
If you were doing the initialization of the SimpleClass object yourself then you can make it work by autowiring the paritcular instance with AutowireCapableBeanFactory in that case the #Autowrire of the service will work since Spring manages also the partical instance of the SomeClass object.
That said, it is not the way to go. Data objects should be isolated from the business logic.
Back to your case, you can't autowire even in the way I mentined because Jackson is the provider of the instance, and Jackson requires the presence of empty constructor.
Since you want some kind of auto-wiring in your SimpleClass bean,
you need to annotate its property SomeService service with #Autowired.
public class SimpleClass {
private String parameter;
#JsonIgnore
#Autowired
private SomeService service;
// getter and setter for parameter (omitted here for brevity)
public void doSomethingFromService(){
//call some methods from the service
}
}
As others already said, ObjectMapper does not do any dependency injection.
But you can combine the #Autowired-ignoring ObjectMapper
with some manually triggered auto-wiring.
For that you need an AutowireCapableBeanFactory which you get by Spring's
normal dependency injection with #Autowired.
Then you use its autowireBean(Object) method
to inject the bean's #Autowired properties.
#Autowired
private AutowireCapableBeanFactory autowireCapableBeanFactory;
public void doSomething(Map<String, Object> value) throws Exception {
ObjectMapper om = new ObjectMapper();
SimpleClass bean = om.convertValue(value, SimpleClass.class);
autowireCapableBeanFactory.autowireBean(bean);
bean.doSomethingFromService();
}
It's not possible. Only objects that have been instanciated with spring can use #Autowired.
It's simple : when you annotate an object with #Service, spring will try to resolve all it's dependency with introspection.
With jackson (or if you try to instanciate an object by yourself) you are totally out of the scope of spring.
And I should had, what you are trying to do (even if it was possible) is not a good practice. You should'n mix your data objects with business processing.
Injection of services is only possible with a framework like Spring, as said previously.
If you are using Spring, annotate your service class with #Service and then as opposed to using #Autowired declare your service private final and inject it using a constructor (IMO I find this works better).
If you aren't using Spring, you'll need to new up an instance of the service and then call that instance - unless of course it's a static...

Spring App SonarQube Issue S3749

I am running into an issue with my Spring Applications and SonarQube. SQ is flagging both examples with "Annotate this member with "#Autowired", "#Resource", "#Inject", or "#Value", or remove it." on the instance variable mapLoadedByDatabaseCalls
Example 1:
#Service
public class Service implements InitializingBean {
#Autowired
private Dao dao;
private Map<Object, Object> mapLoadedByDatabaseCalls;
#Override
public void afterPropertiesSet() throws Exception {
mapLoadedByDatabaseCalls= new HashMap<>(Object.class);
....
}
}
Example 2:
#Service
public class Service {
#Autowired
private Dao dao;
private Map<Object, Object> mapLoadedByDatabaseCalls;
#PostConstruct
private void setMap() {
mapLoadedByDatabaseCalls= new HashMap<>(Object.class);
....
}
}
What is the correct way to instantiate variables after DI has completed?
A more generic solution to this that does not involve any additional annotations, is to initialize the offending variable in the class constructor.
public Service() {
mapLoadedByDatabaseCalls = new HashMap<>();
}
I believe that this is kludgy and that your original code is better, but this will eliminate the SonarQube complaint. Initialize your map in a #Bean, then reference that as #Autowired. Load the map with data in the #PostConstruct.
#Bean
public Map<Object, Object> getMapLoadedByDatabaseCalls() {
return new HashMap<>(Object.class);
}
#Autowired
private Map<Object, Object> mapLoadedByDatabaseCalls;
#PostConstruct
private void setMap() {
...
// load data into the map
mapLoadedByDatabaseCalls.put(key, value);
....
}
From the Spring Documentation > Initialization callbacks section
It is recommended that you do not use the InitializingBean interface
because it unnecessarily couples the code to Spring. Alternatively,
use the #PostConstruct annotation or specify a POJO initialization
method.
Essentially InitializingBean pre-existed in Spring before the JSR-250 support came on Spring 2.5 onwards (including the #PostConstruct annotation)
The rule S3749 describes that Spring #Component, #Controller, #Service, and #Repository classes are singletons by default, meaning only one instance of the class is ever instantiated in the application. Typically such a class might have a few static members, such as a logger, but all non-static members should be managed by Spring. That is, they should have one of these annotations: #Resource, #Inject, #Autowired or #Value.
Having non-injected members in one of these classes could indicate an attempt to manage state. Because they are singletons, such an attempt is almost guaranteed to eventually expose data from User1's session to User2.
Given the above details, Spring should be managing its all non-static members states. It all depends on the use case and should be avoided either using #Autoworied, class constructor or #PostConstruct.
SECURITY WARNING: OWASP A3:2017. This could leak sensitive data

#Autowired does not create members in constructor

I have a bean that is created from context, after which a autowired member is created:
#Service
public class FileDownloadService extends WFWFileDownloadService {
#Autowired
ConfigurationManager configurationManager;
When I use in code manual constructor call:
FileDownloadService fileDownloadService = new FileDownloadService();
I see configurationManager is null, so I have to make manual wiring:
public FileDownloadService() {
configurationManager = new ConfigurationManagerImpl();
}
What am I doing wrong to make autowiring working with manual creating?
When you call the constructor directly, you're just creating an object and not a bean. The support of the #Autowired annotation is a feature of bean.
Ask the Spring context for the bean.
If you attempt to get the bean by using new operator, you will get all autowired beans inside that class as null.
Your service class is annotated with #Service, so to use it you should autowire this service class also.
Sample code to access service bean in other classes is :
#Controller or #Component
public class OtherClass {
#Autowired FileDownloadService fileService;
public void download() {
fileService.downloadFile();
}
}
In order this class to be able to autowire other beans, this class itself should be annotated with #Controller or #Component.
The Answer is simple:
If you manually create the Object, there is no wiring involved. How should Spring know, that you are in need for wiring? Instead of using new, you could use the getBean() method of the application context (Bean Factory). http://static.springsource.org/spring/docs/current/javadoc-api/index.html?org/springframework/beans/factory/BeanFactory.html
http://static.springsource.org/spring/docs/current/javadoc-api/index.html?org/springframework/beans/factory/BeanFactory.html

#Autowired property in bean constructed as MVC method parameter

I'm using the Spring MVC framework. In the code fragment below, is it possible for me to have Spring inject a bean into the MyRequestClass request parameter when it is constructed (ie. using #Autowired or ApplicationContextAware interface)? I need that request object to access one of my singleton Spring beans and would rather not have to create an ApplicationContextAware implementing singleton just for this purpose.
So far, I'm just getting NullPointerExceptions trying to access the beanaroo property with either approach.
#RequestMapping("/**")
#Controller
public class MyController {
#RequestMapping(value = "/mymethod", method = RequestMethod.POST)
public ModelAndView myMethod(#RequestBody MyRequestClass request,
ModelMap modelMap,
HttpServletResponse response) {
...
}
}
eg.
public class MyRequestClass {
#Autowired
private MyInjectedBean beanaroo;
}
I also tried defining a prototype bean of that class in my application context file but it didn't have any effect either.
You can, using #Configurable and aspectJ, but I wouldn't if I were you.
I'd just have the bean have a method that takes MyInjectedBean as param, and call that from the controller.

Categories