Spring #Qualifier value at runtime - java

Is it possible to assign #Qualifier value at runtime. Let's say I have two beans of same type and a class with dependency injection
<bean id="typeA" class="com.debopam.test.Type">
<property name="typevalue" value="Export" />
</bean>
<bean id="typeB" class="com.debopam.test.Type">
<property name="typevalue" value="Import" />
</bean>
public class Product {
private Integer price;
private String name;
#Autowired
#Qualifier("typeB")
private Type type;
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
public Type getType() {
return type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Is there any way to define type in Product class in runtime instead of hard coding/specifying the value? If yes could you please post some code, otherwise is it advisable to use ApplicationContext.getBean("bean name") to load the bean at runtime?

Yes, I see that you defined two beans for a class. The #Qualifier annotation will tell the class which bean has to be used from the spring configuration file

Related

How to use #XmlIDREF and #XmlID

I don't quite understand how #XmlIDREF and #XmlID work together. By using XmlIDREF I only create a reference to the actual element. However what is the use case for XmlID.
I want to create a reference to the class Publication. Is it enough to annotate the publication List with #XmlIDREF?
public class Author {
private String id;
private String name;
private List<Publication> publications = new LinkedList<>();
public Author() {
super();
}
#XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElement
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlIDREF
public List<Publication> getPublications() {
return publications;
}
I want to create a reference to the class Publication.
Is it enough to annotate the publication List with #XmlIDREF?
No, that's only one half of what you need.
You already have this:
With #XmlIDREF you mark the referencing side of the relation
(pointing from Author to Publication).
public class Author {
...
#XmlIDREF
#XmlElement(name = "publication")
public List<Publication> getPublications() {
return publications;
}
...
}
You also need to mark the referenced side (the Publication itself)
by annotating one of its properties with #XmlID, for example like this:
public class Publication {
...
#XmlID
#XmlElement
public String getId() {
return id;
}
...
}
Then you are able to process XML content like this example:
<root>
<publication>
<id>p-101</id>
<title>Death on the Nile</title>
</publication>
<publication>
<id>p-102</id>
<title>The murder of Roger Ackroyd</title>
</publication>
...
<author>
<id>a-42</id>
<name>Agatha Christie</name>
<publication>p-101</publication>
<publication>p-102</publication>
</author>
...
</root>
You see, the XML references (like <publication>p-101</publication>)
are mapped to Java object references (in List<Publication> publications).

How To Represent a class as Spring XML

I have a sample class Person and the setter methods need to manipulate the string passed as its argument before setting it to the object. How do we represent this same class as XML in Spring?
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name.substring(0, name.length()-1);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private int age;
}
You can add below line with relative changes and add it in the spring bean config file.<bean id="referenceName" class="com.stack.overflow.Person"> Read this for more information.
Using XML :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="person" class="com.example.bean.Person">
</bean>
</beans>
Using Bean config class with annotations:
import org.springframework.context.annotation.*;
#Configuration
public class BeanWireConfig {
#Bean
public Person person(){
return new Person();
}
}
Hope this helps..!

Spring + Jackson Content type 'application/json;charset=UTF-8' not supported

When posting with jQuery ajax, I get following error.
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:226)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:148)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:125)
The interesting thing is when I debug
RequestResponseBodyMethodProcessor.java:148
and get the webRequest.getHeader("Content-Type") the value is application/json. Which is pretty normal.
But when it comes to the last method of the chain AbstractMessageConverterMethodArgumentResolver.java:226 Content-Type becomes application/json; charset=utf-8;
Which throws an exception. Here is my code ;
Controller
#RequestMapping(value="/user/set-preference",method=RequestMethod.POST)
#ResponseBody
private boolean set_preference(#RequestBody UserPreference preference)
{
try{
userService.save(preference);
return true;
}catch(Exception ex){
return false;
}
}
Entity
#Entity
public class UserPreference extends BaseEntity{
#ManyToOne(fetch=FetchType.LAZY)
private User user;
private String name;
private String information;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInformation() {
return information;
}
public void setInformation(String information) {
this.information = information;
}
}
Spring MVC Config
<mvc:annotation-driven>
<mvc:message-converters>
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean
class="com.test.HibernateAwareObjectMapper" />
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
I had the same problem and I solved it adding a default constructor to my class. Try it.

Not able to autowire a bean using constructor in Spring

Im new to spring. I'm trying to autowire a bean using constructor using spring. Here is the code
<bean id="location" class="com.ibm.spring.Location">
<constructor-arg name="pincode" value="110976"></constructor-arg>
</bean>
<bean id="address" class="com.ibm.spring.Address">
<property name="id" value="2"></property>
<property name="street" value="shahjahan"></property>
</bean>
location class
public class Location {
private Address address;
private String pincode;
public void setAddress(Address address) {
this.address = address;
}
#Autowired
public Location(Address address, String pincode) {
super();
this.address = address;
this.pincode = pincode;
}
public void getTotalAddress() {
System.out.println(this.pincode + "::"+this.address);
}
}
Address class
public class Address {
private int id;
private String street;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = "Kkp";
}
#Override
public String toString() {
return "Address [id=" + id + ", street=" + street + "]";
}
Tester
public class SpringTester {
public static void main(String[] args) {
String configLoc = "com/ibm/spring/config/applicationContext.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configLoc);
Location l = (Location) ctx.getBean("location");
l.getTotalAddress();
}
}
I'm setting one of the field value through constructor arg. and class should be injected. WHat could be the problem here?
The error log says
Error creating bean with name 'location' defined in class path resource [com/ibm/spring/config/applicationContext.xml]: Unsatisfied dependency expressed through constructor parameter 0: Ambiguous argument values for parameter of type [com.ibm.spring.Address] - did you specify the correct bean references as arguments?
It seems like Location has two arguments so:
<bean id="location" class="com.ibm.spring.Location">
<constructor-arg name="pincode" value="110976"></constructor-arg>
<constructor-arg ref="address"></constructor-arg>
</bean>

Vaadin BeanFieldGroup - "Property is not cascaded" when binding nested property

I've been searching for hours on here and on the Vaadin forums, but I seem to have a unique problem here.
I simplified my problem a lot to be able to illustrate it easily.
So I have a Bean class:
public class Bean {
private String name;
private NestedBean nestedBean;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public NestedBean getNestedBean() {
return nestedBean;
}
public void setNestedBean(NestedBean nestedBean) {
this.nestedBean = nestedBean;
}
Bean() {
this.name = "Bean";
this.nestedBean = new NestedBean();
}
}
And its nested field, class NestedBean:
public class NestedBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
NestedBean() {
this.name = "NestedBean";
}
}
So now I want to bind an instance of Bean to two TextFields, with the help of a BeanFieldGroup:
Bean bean = new Bean();
BeanFieldGroup<Bean> binder = new BeanFieldGroup<>(Bean.class);
binder.setItemDataSource(bean);
addComponent(binder.buildAndBind("Name", "name"));
addComponent(binder.buildAndBind("Nested name", "nestedBean.name"));
This, however, throws this exception:
java.lang.IllegalArgumentException: Property com.reygok.vaadin.main.Bean.nestedBean is not cascaded
Caused by: org.apache.bval.jsr.UnknownPropertyException: Property com.reygok.vaadin.main.Bean.nestedBean is not cascaded
I tried different solutions, like:
Creating the TextFields first and then using
binder.bind(textField, "nestedBean.name");
Doing this first:
binder.getItemDataSource().addNestedProperty("nestedBean.name");
But nothing changed the Exception. So does someone know what causes this?
Thanks a lot in advance!
I found it, so if others have the same problem:
The solution is to add the #Valid annotation to the fields that have nested fields inside of them.
So in my example:
public class Bean {
private String name;
#Valid
private NestedBean nestedBean;
...
I recommand you to bind member before setting bean data source
BeanFieldGroup<Bean> binder = new BeanFieldGroup<>(Bean.class);
// first
addComponent(binder.buildAndBind("Name", "name"));
addComponent(binder.buildAndBind("Nested name", "nestedBean.name"));
// then
binder.setItemDataSource(bean);

Categories

Resources