Collection Merge in Java Spring using beans - java

I am new to Spring Framework.I am trying to merge two sets using spring.
Beans.xml
<bean name = "mainAccount" class="java.util.HashSet">
<constructor-arg>
<set>
<value>123</value>
<value>1234</value>
</set>
</constructor-arg>
</bean>
<bean name = "subAccount" class="java.util.HashSet" parent="mainAccount">
<constructor-arg>
<set merge="true">
<value>231</value>
<value>23221</value>
</set>
</constructor-arg>
</bean>
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld">
<constructor-arg name="AccountIDs" ref="subAccount" />
</bean>
I am not able to merge the sets in to the subAccount set.
I am getting the exception :-
Related cause:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'subAccount' defined in class path resource [Beans.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [int]: Could not convert constructor argument value of type [java.util.LinkedHashSet] to required type [int]: Failed to convert value of type 'java.util.LinkedHashSet' to required type 'int'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.util.LinkedHashSet] to required type [int]: PropertyEditor [org.springframework.beans.propertyeditors.CustomNumberEditor] returned inappropriate value of type [java.util.LinkedHashSet]
My HelloWorld.java is :-
package com.tutorialspoint;
import java.util.HashSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
public class HelloWorld {
private final Set<String>AccountIDs;
public HelloWorld(Collection<String> AccountIDs){
this.AccountIDs = new HashSet<String>(AccountIDs);
Iterator iterator = AccountIDs.iterator();
while (iterator.hasNext())
System.out.print( iterator.next() + ", " );
System.out.println();
}
}
When I pass parent bean set "mainAccount" then it is showing the set values properly but when I try to pass the child bean "subAccount" I got the error.I want to merge the mainAccount to subAcount.I tried all posssible ways but not able to solve this.Some guidance would be helpful.

The issue here that i see is, the way you are trying to merge the collection. You are creating a instance of a collection and hoping that the merging will occur during construction of the Set.
How spring merging works is, you will have to define your own bean (Parent) with a property of collection say Set with property name say mySet, and then you can define your child bean with the same property name and declare the set's merge attribute to true. Thats when spring will understand which collection to merge with what.
You can follow below URL to see how its done
Collection Merging

Updated Beans.Xml. I have to add index.
<bean name = "mainAccount" class="java.util.HashSet">
<constructor-arg index="0">
<set>
<value>123</value>
<value>1234</value>
</set>
</constructor-arg>
</bean>
<bean name = "subAccount" class="java.util.HashSet" parent="mainAccount">
<constructor-arg index="0">
<set merge="true">
<value>231</value>
<value>23221</value>
</set>
</constructor-arg>
</bean>
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld">
<constructor-arg name="AccountIDs" ref="subAccount" />
</bean>

Related

Getting Circular placeholder reference error for specific key

I am getting Circular reference error if my placeholder key starts with "database"
This config gives error.
<bean id="paymentTransactionLogMessageDecoratorDao"
class="com.gsicommerce.payment.dao.PaymentTransactionLogMessageDecoratorDao">
<constructor-arg ref="paymentTransactionLogMessageDao"/>
<constructor-arg value="${database.payments.logging.enabled}"/>
</bean>
Error: Circular placeholder reference
'database.payments.logging.enabled' in property definitions
When we change the key name like this,
<bean id="paymentTransactionLogMessageDecoratorDao"
class="com.gsicommerce.payment.dao.PaymentTransactionLogMessageDecoratorDao">
<constructor-arg ref="paymentTransactionLogMessageDao"/>
<constructor-arg value="${payments.database.logging.enabled}"/>
</bean>
this works. Do we have any reserve key words ("database") ?
As you can see, its a constructor injection and the property name is completely different.
public paymentTransactionLogMessageDecoratorDao(PaymentTransactionLogPersistenceServicetransactionLogMessageDao,
boolean databaseLoggingEnabled) {
this.transactionLogPersistenceService = transactionLogMessageDao;
this.databaseLoggingEnabled = databaseLoggingEnabled;
}
Probably your are using maven resource filtering: in this case, as detailed in this post, the keys of the property value to filter and it’s respective Spring property-placeholder cannot be the same.

Creating 2 beans of the same class with different constructor-args and using autowiring

Hi I working on a project, in which I need to create 2 instances of bean of same class but different constructor-args. Right now have functionality only for "production environment", so I have xml file like:
<context:component-scan base-package="com.xxx.yyy" />
<bean id="id1" class="someCompanySpecificURLForTheClass" scope="singleton"/>
<bean name="name1" factory-bean="id1" factory-method="createFullClient">
<constructor-arg index="0">
<ref bean="someJSONBean"/>
</constructor-arg>
<constructor-arg value="productionEnv" index="1"/>
</bean>
</beans>
Now I need to include functionality for testing environment also. So I changed the xml file to:
<context:component-scan base-package="com.xxx.yyy" />
<context:component-scan base-package="com.zzz.yyy" />
<bean id="id1" class="someCompanySpecificURLForTheClass" scope="prototype"/>
<bean name="name1" factory-bean="id1" factory-method="createFullClient">
<constructor-arg index="0">
<ref bean="someJSONBean"/>
</constructor-arg>
<constructor-arg value="${value.name}" index="1"/>
</bean>
In the 2 Java files, I use #Autowired annotations on the method of setClients() and on creating object of someJSONBean.
But I am receiving errors:
BeanCreationException: could not autowire method: public void com.zzz.yyy.sometthing.setClients(someCompanySpecificURLForTheClass) throws IllegalArgumentException and UnsupportedEncodingException.
nested exception is defined: NoSuchBeanDefinitionException: no unique bean of type(someCompanySpecificURLForTheClass) is defined: expected single matching bean, found 2(name1, name2).
I am new to spring framework. can anyone tell whats happening wrong, is the autowiring that i am doing wrong? how can i solve this?
Edit:
Here someCompanySpecificURLForTheClass is the same class and beans(name1 and name2) use this bean as a factory bean with different constructor-arguments.
I am using spring 3.1.
After searching a lot, I think I can use placeholder for the constructor-args value right?
The above is the edited xml file being used.
Updated code in the Java classes:
1.
#ConfigAdapter
class class1{
#Autowired
private someJSONBean obj;
#Autowired
#Value("${value.name:thisismyvalue}")
public void setClients(){}
}
#ConfigAdapter
class class2{
#Autowired
private someJSONBean obj;
#Autowired
#Value("${value.name:thisismyvalue}")
public void setClients(){}
}
But I get the following error:
ConversionNotSupportedException: failed to convert 'java.lang.string' to 'someCompanySpecificURLForTheClass'.
nested execption is IllegalStateException
Cannot convert 'java.lang.string' to 'someCompanySpecificURLForTheClass' of required type: no matching editors or conversion strategy found.
Am I specifying the annotation value wrongly?
Why is this happening?
You have to use #Qualifier Annotation along withe #Autowired. Since your are creating two beans of the same class, spring does not know which one to autowire. You can give a hint using #Qualifer("id/name") annotation.
#Autowired
#Qualifier("name1")
//yourProperty
or
#Autowired
#Qualifier("name2")
//yourProperty
Check out this link .
If you want to inject both the beans into your class, then your have two create two different properties, each pointing to a different instance.
#Autowired
#Qualifer("name1")
//property1
#Autowired
#Qualifer("name2")
//property2

Spring XML configuration - how to define Instant, BigDecimal, ... parameters?

How do I specify a constructor argument that is not a primitive value (or a simple type like a String) but still a class part of the Java library in the XML configuration file ?
The XML works so far for me for simple values, e.g.
<bean id="foo" class="app.model.provider.IFoo">
<constructor-arg name="bar" value="baz"/>
</bean>
How do I define a dependency that requires e.g. a java.time.Instant instance in its constructor?
Spring allows you to use factory methods to get instances.
Say you wanted to do the equivalent of
Instant.now();
you would use
<bean id="anInstant" class="java.time.Instant" factory-method="now"/>
If you want to do
Instant.parse("2015-07-24T17:10:00Z")
you would use
<bean id="anInstant" class="java.time.Instant" factory-method="parse">
<constructor-arg value="2015-07-24T17:10:00Z" />
</bean>
However, I wouldn't create accessible Instant beans. If you need to pass them to some other bean's constructor, provide them directly, without names
<bean id="example" class="com.example.Example">
<constructor-arg name="startTime">
<bean class="java.time.Instant" factory-method="parse">
<constructor-arg value="2015-07-24T17:10:00Z" />
</bean>
</constructor-arg>
</bean>

Setting marshalTo in MarshallingMessageConverter in XML configuration getting Invalid property 'marshalTo'

I'm trying to create a MarshallingMessageConverter, here is my XML:
<bean id="marshallingMessageConverter" class="org.springframework.jms.support.converter.MarshallingMessageConverter">
<property name="marshaller" ref="marshaller" />
<property name="unmarshaller" ref="marshaller" />
<property name="marshalTo" value="MARSHAL_TO_TEXT_MESSAGE" />
</bean>
I am getting the following error:
Error setting property values; nested exception is
org.springframework.beans.NotWritablePropertyException:
Invalid property 'marshalTo' of bean class
[org.springframework.jms.support.converter.MarshallingMessageConverter]:
Bean property 'marshalTo' is not writable or has an invalid setter method.
Does the parameter type of the setter match the return type of the getter?
Is this because MarshallingMessageConverter doesn't have a getMarshalTo method, and so setting it in this way isn't working?
It looks like it should be possible, as I found https://jira.spring.io/browse/SWS-614, and someone else said they have the following config working:
<bean id="marshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"/>
<bean id="xstream" class="org.springframework.oxm.support.MarshallingMessageConverter"
p:marshaller-ref="marshaller" p:unmarshaller-ref="marshaller" p:marshalTo="2"/>
<!--marshalTo=2 sets the marshaller to text message rather than bytes message-->
So I feel like maybe it's something I'm missing. I've tried using an int in the value, but that doesn't work either.
I want to use XML config because I'm using Spring Integration, and don't want to be pulling beans out of the app-context using Java.
I am using Spring version 3.2.1.RELEASE.
I was missing something... I was looking at the documentation for
org.springframework.oxm.support.MarshallingMessageConverter
but the one that I was using was
org.springframework.jms.support.converter.MarshallingMessageConverter
which has the method, toTargetType().
Not sure if I should delete my question or leave it here in case someone else does the same thing.

Injecting a reference bean from jar file, No bean named *** is defined exception is thrown

<bean id="org.sakaiproject.vidyayug.tool.SakaiStyleSelectorInterceptor"
class="org.sakaiproject.vidyayug.tool.SakaiStyleSelectorInterceptor">
<property name="worksiteManager">
<ref bean="org.sakaiproject.metaobj.worksite.mgt.WorksiteManager"/>
</property>
</bean>
I am injecting ref bean from a jar file..
Exception is:
Cannot resolve reference to bean 'org.sakaiproject.metaobj.worksite.mgt.WorksiteManager' while setting bean property 'worksiteManager';
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'org.sakaiproject.metaobj.worksite.mgt.WorksiteManager' is defined
You must add a
<bean id="org.sakaiproject.metaobj.worksite.mgt.WorksiteManager" class="org.sakaiproject.metaobj.worksite.mgt.WorksiteManager"/>
in your application context.
Bean id and class name are not the same thing, even if you're giving them the same value.
The bean id should be a "handy" name you use to refer to a bean isntance, while the class is the actual fully qualified class name to load the bean from the classpath (jar or your class folder or whatever).
do like that, give a bean id, and then call the reference by calling that id.
<bean id="Order" class="com.classes.OrderPizza">
<property name="pizzaTemp" ref="ChickenPizza"></property>
</bean>
<bean id="ChickenPizza" class="com.classes.ChickenPizza"></bean>
<bean id="PaneerPizza" class="com.classes.PaneerPizza"></bean>
The problem is that you are referencing a bean without instantiating it. Correct your code this way:
<bean id="org.sakaiproject.vidyayug.tool.SakaiStyleSelectorInterceptor" class="org.sakaiproject.vidyayug.tool.SakaiStyleSelectorInterceptor">
<property name="worksiteManager">
<bean class="org.sakaiproject.metaobj.worksite.mgt.WorksiteManager"/>
</property>
</bean>
NOTE You also have to be sure the jar is deployed in your project binaries.

Categories

Resources