How to load two ResourceBundles and inject them separately - java

I am using Spring for loading localized resource bundles into my application. Here is what I have done.
<bean id="systemMessages" class="o.s.c.s.ResourceBundleMessageSource">
<property name="basename" value="locale/system">
</bean>
<bean id="clientMessages" class="o.s.c.s.ResourceBundleMessageSource">
<property name="basename" value="locale/client">
</bean>
I want to load messages based on the locale in my controller, and I tried both these ways below
#Autowired
#Qualifier("clientMessages")
ResourceBundleMessageSource clientMessages;
#Resource(name="systemMessages")
ResourceBundleMessageSource systemMessages;
EDIT
The application is a JAXRS application and the injection is being tried in a Global Exception Mapper. From the comments I now understand that this class would have been created by the JAXRS container and not Spring ( Code below). How to let Spring know that this injection must work?
import javax.ws.rs.WebApplicationException;
//other imports
public class GlobalWebApplicationException extends WebApplicationException{
private String systemMessage;
private String clientMessage;
//Autowire the multiple resourcebundles
public GlobalWebApplicationException (String key, Locale locale) {
// this is where I want to use the injected object fetch the property
}
public doSomething(){
// Business Logic
}
}
But the injection is not happening and I am getting an NPE. How do I achieve this?

When using Spring and having it do auto wiring using annotations the fields cannot be null. The dependencies need to be satisfied on startup of the application. If that doesn't happen there can be 1 of 2 things wrong
You haven't enabled annotation processing
You aren't using a spring managed bean but are creating instances yourself
For the first option add <context:annotation-config /> to your application context, or if you want to do component scanning add <context:component-scan /> the latter already implies annotation processing.
For the second option you need to make your bean a spring managed bean and use that instead of creating new instances yourself.

Related

Auto-wire third party library in my spring managed component

I am using a third party library in my application to do some task. They have provided a wrapper that I've added in my project using maven. For using this wrapper we have to give an access key to their client class in order to use it's functionality. For ex:
final WeatherApiService was = new WeatherApiServiceImpl(accessKey);
final WeatherApiClient weatherApiClient = new WeatherApiClient(was);
What I want is to remove the above code (Since it's kind of Singleton and should be registered in spring context when the application is being started) and do something so that I can just autowire the WeatherApiClient and we are good to go. (wrapper isn't using spring FYI). Below is what I did is in my spring context I registered two beans and put the access-key is web.xml.
spring-context.xml
<bean id="was" class="my.librarypath.WeatherApiService ">
<constructor-arg type="java.lang.String" value="${accessKeyFromWebXml}"/>
</bean>
<bean id="weatherApiClient" class="my.librarypath.WeatherApiClient">
<constructor-arg type="my.librarypath.WeatherApiService" value="was"/>
</bean>
my component that will use the third party library
#Component("myComponent")
public class MyComponent IComponent {
#Resource(name = "weatherApiClient") // <--- getting Error here i.e: Couldn't aurtowire, bean should be of String type
private String weatherApiClient;
public void myFunction() {
weatherApiClient.getWeather();
}
}
Can someone confirm if I'm doing it right or is there any best practices options available !?
Ther were two issues:
<bean id="weatherApiClient" class="my.librarypath.WeatherApiClient">
<constructor-arg type="my.librarypath.WeatherApiService" value="was"/>
// ^---- should be ref
</bean>
Secondly, I was using String instead of WeatherApiClient. MY BAD :/
#Resource(name = "weatherApiClient")
private String weatherApiClient;
// ^---- this one should have to be WeatherApiClient

Spring without getBean(..)

I'm trying to get a better understanding of the #Autowired annotations component scanning, but all the examples I found so far use context.getBean(..) at some point to get at least one Bean to start with.
I also read that doing that is considered bad practice , but I can't seem to find any information on how to do it without context.getBean(..)
Could somebody please enlighten me with an example and information on how to do this ?
Define your bean in xml and use
<context:component-scan base-package="com" />
<mvc:annotation-driven />
Bean def
<bean id="processEngine" class="com.processEngine">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
now you can get bean as following
#Autowired
private ProcessEngine processEngine;
how it works
spring scans the bean's recipes either from xml or java configuration. then spring creates a beanDefinitions which are 'loaded' into BeanFactory. BeanFactory triggers a set of BeanPostProcessors (BPP) which are scanning classes for particular annotations like Autowired/Resource/PostProcessor and etc. and do appropriate actions. in case when your class contains #Autowired annotation, AutowiredAnnotationBeanPostProcessor would auto wire required field (dependencies), and when creation of an object is done and all BPP worked out, object is ready to be used by the app, from this point your code can get 'ready' objects from container.
there are some cases when you would need to access this beans from the code which is out of spring's control and not managed by container. in order to do so, you would need to get the ApplicationContext (container) and call #getBean specifying either name or type. using applicationContext directly is not a good practice because there are some problems that you can come to, f.ex. id of a bean might be changed and if you refer to bean by id then NPE would be thrown.
configuration
there are several approaches to configure spring to scan the classes for finding bean recipes. one would be defining component-scan, in this case classes which are located in the path that you've set and having any of valid spring annotations like #Component, #Service, #Repository, #Controller (for web container) would be considered. another way would be specifying each bean separately using <bean> or #Bean.
examples.
if you want to create a web app then you should see DispatcherServlet with ContextLoaderListener classes. this classes would boot your app and load everything according to configuration. f.ex. here,
but if you want to create a desktop app, then you would end up with something like this
From time to time (usually when not using Spring Boot), I use something along the lines of the following code:
public static <T> T autowire(ApplicationContext ctx, T bean) {
ctx.getAutowireCapableBeanFactory().autowireBean(bean);
return bean;
}
In my main, I create an instance of the main application class that contains a few #Autowired annotations for the main services / entry points to my Spring application.

Spring: Xml based Autowiring a list of beans by interface type

With Spring it is possible to inject a list of beans by the interface class like:
#Component
public class Service {
#Autowire
private List<InterfaceType> implementingBeans;
...
}
All defined beans that implement this interface will be present in this List.
The annotation based approach is not possible for me, as the Service class is in a module that must not have spring dependencies.
I need to use this mechanism from outside via xml configuration.
<bean id="service" class="...Service">
<property name="implementingBeans">
??? tell spring to create a list bean that resolves all beans of the interfaceType.
</property>
</bean>
Does anyone know how to solve this?
EDIT: Additionally, there are more than one spring applications that use this service. So the best solution would be to handle this szenario completely via xml configuration. I can then copy the xml parts to all spriong applications that need this.
I want to avoid having a kind of initializer bean that gets the service injected and must then be copied to all spring applications.
Kind regards.
An XML-only solution would simply have you declare a <bean> of the "external" type and provide an autowire value of "byType".
Controls whether bean properties are "autowired". This is an
automagical process in which bean references don't need to be coded
explicitly in the XML bean definition file, but rather the Spring
container works out dependencies.
[...]
"byType" Autowiring if there is exactly one bean of the property type in the container. If there is more than one, a fatal error is
raised, and you cannot use byType autowiring for that bean. If there
is none, nothing special happens.
The explanation is a little confusing in that we expect multiple InterfaceType beans, but the actual field is of type List and Spring will be able to dynamically instantiate one and add all the InterfaceType beans to it, then inject it.
Your XML would simply look like
<bean id="service" class="...Service" autowire="byType">
</bean>
My original suggested solution made use of SpEL.
In the module that does have Spring dependencies, create a DTO
#Component(value = "beanDTO")
public class BeanDTO {
#Autowire
private List<InterfaceType> implementingBeans;
public List<InterfaceType> getImplementingBeans() {
return implementingBeans;
}
}
and then use SpEL to retrieve the value of implementingBeans from the beanDTO bean.
<bean id="service" depends-on="beanDTO" class="...Service">
<property name="implementingBeans" value="{beanDTO.implementingBeans}" />
</bean>
Spring will create the BeanTDO bean, inject all the beans that are of type InterfaceType. It will then create the service bean and set its property from beanDTO's implementingBeans property.
Following comments on question:
In an effort to be more JSR 330 compliant, Spring has introduced support for Java EE's javax.inject package. You can now annotate your injection targets with #javax.inject.Inject instead of #Autowired. Similarly, you can use #Named instead of #Component. The documentation has more details.

Declaration of beans in applicationContext.xml

I have a question regarding declaration of classes in applicationContext.xml
In applicationContext.xml do we need to specify all the classes from the application?
E.g.
In my small web application I have a Entity class, Service class and DAO class. So currently it is defined as
<!-- Beans Declaration -->
<bean id="Employees"
class="net.test.model.Employees" />
<!-- User Service Declaration -->
<bean id="
EmployeeService" class="net.test.employees.service.EmployeeService">
<property name="employeesDAO" ref="EmployeeDAOImpl" />
</bean>
<!-- User DAO Declaration -->
<bean id="EmployeeDAO" class="net.test.employee.dao.EmployeeDAOImpl">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
So if I have multiple entity, service and dao classes do I need to mention all those classes in applicationContext.xml?
Any insight into this is highly appreciable.
Regards
Update 1
ManagedBean
#ManagedBean(name="empMB")
#Named
#Scope("request")
public class EmployeesManagedBean implements Serializable {
and I have Inject annotation
#Inject
EmployeesService employeesService;
In EmployeesService I have annotations like
#Named
public class EmployeesService implements IEmployeesService {
#Inject
EmployeesDAO employeesDAO;
#Override
public List<Employees> getEmployees() {
return getEmployeesDAO().getEmployees();
}
and finally in applicationContext.xml I have
<context:component-scan base-package="net.test" />
Now the problem is when I run my application I am getting
java.lang.NullPointerException at
net.test.managed.bean.EmployeesManagedBean.getEmpList(EmployeesManagedBean.java:53)
What am I doing wrongly to get nullpointer exception?
In applicationContext.xml do we need to specify all the classes from
the application?
No. Declaring model classes like your net.test.model.Employees is pointless unless you need a prototype to work with, something like initializing its values, but you can do this directly in the class and just instantiate it.
So if I have multiple entity, service and dao classes do I need to
mention all those classes in applicationContext.xml?
As I explained before, entity classes no. Services and DAOs are ok because most of the time you need DAOs injected to the Services (and that's the point of DI). But of course, if you create 3 DAOs and you want them to be injected in your 3 Services, then mention them in your Spring XML Bean Definition file (what you call applicationContext.xml).
But one thing, you may want to use package scanning autodetection and annotation based config to avoid writing everything in your Bean Definition File.
The bean declaration in the application context is to register the bean in the application container.
If the bean is not registered, the container wouldn't be able to dependency inject any instance of that class, or apply interceptors to the object of the class.
So unless the reference of bean is not required for any task like intercepting it or inject it, or create default singleton object of it, there is no need to declare it in the applicationContext.xml
Hope this helps.
Ideally yes, another way can be using Spring Annotations so that you don't to add multiple entries in xml.

benefit of #Autowired annotation in Java

Maybe, because of my wrong English, I couldn't understand the benefit of using #Autowired annotation.
According to the tutorial we can simplify the first(I.) case to second case(II.) by means of #Autowired.
My question is, what is the meaning of the #Autowired ? Because it doesnt tell any more, since without using #Autowired the compiler can figure out that "EmpDao emDao" and "EmpManager" are closely related according the declaration.
code cited from here
I.
<bean id="empDao" class="EmpDao" />
<bean id="empManager" class="EmpManager">
<property name="empDao" ref="empDao" />
</bean>
public class EmpManager {
private EmpDao empDao;
public EmpDao getEmpDao() {
return empDao;
}
public void setEmpDao(EmpDao empDao) {
this.empDao = empDao;
}
...
}
II.
<context:annotation-config />
<bean id="empManager" class="autowiredexample.EmpManager" />
<bean id="empDao" class="autowiredexample.EmpDao" />
import org.springframework.beans.factory.annotation.Autowired;
public class EmpManager {
#Autowired
private EmpDao empDao;
}
#Autowired is spring-specific. #Inject is the standard equivallent. It is an annotation that tells the context (spring, or in the case of #Inject - any DI framework) to try to set an object into that field.
The compiler has nothing to do with this - it is the DI framework (spring) that instantiates your objects at runtime, and then sets their dependencies at the points you have specified - either via XML or via an annotation.
I agree it is a possible scenario for a DI framework to try to inject dependencies into all fields, even if they are not annotated. (And if you want to exclude a particular field, to annotate it). But they chose the other strategy (configuration-over-convention). By the way:
if using xml config and choose some form of autowiring, the dependencies of the bean will be automatically autowired without the need to specify anything
you can specify per-context autowiring settings.
When the server bootstraps itself. It finds
<context:annotation-config />
in the application context and then goes through the classes defined in the contexts. If there are any beans that are autowired, it injects that into the class by referring the context file.
Basically, it promotes convention over configuration. That's what most frameworks do these days to reduce the development time.
the #Autowired Spring annotation tells Spring to for a bean named 'empDao' and inject it into the EmpManager class, without you having to add the empDao bean as a property in your spring config file.
#Autowired tells Spring to find a bean of the declared type and wire in that bean, rather than requiring an explicit lookup by bean name. It can, under certain circumstances, make configuring applications easier if you only have one implementation of your types in a given Spring context.

Categories

Resources