Updating Spring xml configured controller to Annotations - java

I have been tasked with updating a old project that I did not write.
The project is Spring MVC based and has an older Spring Controller configuration that I am unfamiliar with.
The controllers have bean configurations as follows
<bean id="controllerName" class="the.project.controller.class">
<property name"serviceName">
<ref bean="serviceName">
</property>
<property name"successView">
<value>viewName</value>
</property>
</bean>
where serviceName refers to a class annotated with #Service as follows
#Service(value=serviceName)
Is this the correct replacement for the xml configuration ?
#Autowired
#Qualifier("serviceName")
ServiceNameImpl serviceName
thanks
edit here is the organization of the serviceName class and interface
public interface ServiceName {
// methods omitted
}
#Service(value="serviceName")
public class ServiceNameImpl implments ServiceName {
//methods omitted
}
The #Resource annotation is not available to me ( Spring 3.0.7) and Autowire as above fails ( as it appears the type is not as expected as described below )
org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching beans of type [the.project.ServiceNameImpl] found for dependency
Given the edits, what am I doing wrong here ( Apologies for leaving out this information )?
in the end I need to be able to access the methods of the interface and its implementation
for example
serviceName.doSomething(someVar);

That's correct, but consider using private modifier for serviceName. Another way would be to use #Resource:
#Resource
private ServiceNameClass serviceName;
Note that in this case you don't need a #Qualifier("serviceName") - #Resource autowires by (field) name while #Autowired uses type by default. Only a problem when you have several beans of the same/compatible type.
Also you can skip the controllerName bean definition altogether by annotating controller class with #Controller.
BTW you can also shorten the XML configuration a bit by using the following syntax:
<bean id="controllerName" class="the.project.controller.class">
<property name"serviceName" ref="serviceName"/>
<property name"successView" value="viewName"/>
</bean>
(IntelliJ suggests this transformation and performs it for you).

Related

Spring JavaConfig equivalent of referring to beans by name

In Spring XML config, I can use the ref="bean_name" syntax to refer to a bean by ID or name.
<bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
Is there an equivalent way of achieving this in Java config, using the name attribute on the #Bean annotation? I've used the #Named annotation (javax.inject.Named) and have seen #Qualifier suggested elsewhere, but is a separate annotation really necessary if we already have a name attribute on the #Bean annotation?
#Qualifier is the correct thing to use here.
#Autowired
#Qualifier("bean_name")
private Beantype var;
And declaring your component
#Component(value = "bean_name")
public class Beantype {...}
At least that works for me.

Why is a Spring ProxyFactoryBean implicit definition working?

I have the following definition:
<bean id="myInterceptor" class="info.fastpace.MyInterceptor"/>
<bean id="alikProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="myClass"/>
<property name="interceptorNames">
<list>
<value>myInterceptor</value>
</list>
</property>
</bean>
I have 2 classes defined: MyInterceptor and MyClass.
The peculiar thing is that Spring knows to invoke the interceptor before invoking class MyClass (capital M), even though the class isn't configured in the commonContext.xml file. The only hint is the myClass (lowercase m) in the proxy bean definition.
When removing the alikProxy bean definition, the interceptor isn't invoked.
How does Spring know to invoke the interceptor for MyClass using an undefined myClass ref?
Looks like you defined a bean of class MyClass, but did not give it any name explicitly, so Spring just gave it a default name myClass, based on class name MyClass.
Update
I suppose somewhere in your Spring context xml you have <context:component-scan> element.
Here is a fragment of book Spring In Action, 3rd Edition:
By default, <context:component-scan> looks for classes that are annotated with one
of a handful of special stereotype annotations:
#Component—A general-purpose stereotype annotation indicating that the class
is a Spring component
...skipped...
For example, suppose that our application context only has the eddie and guitar beans in it. We can eliminate the explicit <bean> declarations from the XML configuration by using <context:component-scan> and annotating the Instrumentalist and Guitar classes with #Component.
...skipped...
When Spring scans the com.springinaction.springidol package, it’ll find that
Guitar is annotated with #Component and will automatically register it in Spring. By default, the bean’s ID will be generated by camel-casing the class name. In the case of Guitar that means that the bean ID will be guitar.

injecting beans into spring java config classes

I have a configuration class which uses the #Configuration annotation and also extends the RepositoryRestMvcConfiguration.
as part of the extended class, there are overridable methods that allow configuration of the bean recipes. one of which is configuring the conversion services available to the spring component.
I would like to inject some beans into a list that is iterated over and added as a conversion service through this overrided method, My configuration java class is defined below:
#Configuration
#EnableJpaRepositories(basePackages = "com.example.model.repositories")
public class DataConfig extends RepositoryRestMvcConfiguration {
List<Converter<?,?>> converters;
//get
//set
#Override
protected void configureConversionService(ConfigurableConversionService conversionService){
for(Converter converter : converter){
conversionService.addConverter(converter);
}
}
}
The following defines my converters that i wish to inject in the app-context.xml file
<beans>
<bean id="fooToBarConverter" class="com.example.model.converters.FooToBarConverter" />
<bean id="barToFooConverter" class="com.example.model.converters.BarToFooConverter" />
<util:list id="myConverters" value-type="org.springframework.core.convert.converter.Converter">
<ref bean="barToFooConverter"/>
<ref bean="fooToBarConverter" />
</util:list>
</beans>
Is there a better way of providing these converters through spring configuration or do i need to explicitly list them as output of a function contained within my configuration class like:
#Bean
public List<Converter<?,?> myConverters(){
Arrays.asList(new FooToBarConverter(), new BarToFooConverter());
}
Your help is highly appreciated.
P.S. since you are so good at spring, would you mind having a look at my spring-data-rest-mvc related question? please and thank you.
By default, any #Autowired (or #Resource) annotated Collection (or List, Set, etc) of a certain type will contain all beans of that type discovered in the context. You could add an #Autowired in your setter and let Spring injects your controller for you.
If you need a more fine-grained control over which converters should be configured and which one should not, maybe you should configure the ConversionService altogether instead.

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.

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