here is some code from a post here that would explain my question:
Interface:
package org.better.place
public interface SuperDuperInterface{
public void saveWorld();
}
Implementation:
package org.better.place
import org.springframework.stereotype
public class SuperDuperClass implements SuperDuperInterface{
public void saveWorld(){
System.out.println("Done");
}
}
Client:
package org.better.place
import org.springframework.beans.factory.annotation.Autowire;
public class SuperDuperService{
private SuperDuperInterface superDuper;
public void doIt(){
superDuper.saveWorld();
}
public void setSuperDuper(SuperDuperInterface superDuper) {
this.superDuper = superDuper;
}
}
My question is - how can I configure the beans in the spring config? I don't want to use #Autowired and other annotations.
I guess it will be something like this:
<bean id="superService" class="org.better.place.SuperDuperService">
<property name="superDuper" ref="superWorker"
</bean>
<bean id="superWorker" class=?????? parent=???????? >
</bean>
You will have to instantiate the implementing class, of course:
<bean id="superWorker" class="org.better.place.SuperDuperClass"/>
You would only need the parent attribute if you wanted to create multiple beans with common properties that you don't want to repeatedly declare, so you move it to an abstract parent bean definition that the concrete bean definitions can reference.
Assuming the SuperDuperClass has some properties:
<bean id="superWorkerPrototype" abstract="true"
class="org.better.place.SuperDuperClass">
<property name="prop1" value="value1"/>
<property name="prop2" value="value2"/>
</bean>
<bean id="superWorker1" parent="superWorkerPrototype"
class="org.better.place.SuperDuperClass">
<property name="prop3" value="foo"/>
</bean>
<bean id="superWorker2" parent="superWorkerPrototype"
class="org.better.place.SuperDuperClass">
<property name="prop3" value="bar"/>
</bean>
Which would result in both instances having the same values for prop1 and prop2, but different ones for prop3.
You can just give the implementation class's fully qualified name, and its not required to give parent attribute. Spring will automatically find if it can assign an instance of SuperDuperClass to the superDuper field of SuperDuperService
<bean id="superWorker" class="org.better.place.SuperDuperClass" >
</bean>
Related
I have a class that takes a java.time.Clock object as a constructor argument.
I am having problems defining this as a bean in the applicationContext.xml file:
TimeTracker.java
public class TimeTracker{
public final Clock clock;
public TimeTracker(Clock clock){
this.clock = clock;
}
applicationContext.xml
<bean id="timeTracker"
class="com.tracker.TimeTracker">
<constructor-arg type="java.time.Clock" value=""/>
</bean>
The error I am having is: Ambiguous constructor argument types - did you specify the correct bean references as constructor arguments?
Try it like this:
<bean class=“java.time.Clock” factory-method=“java.time.Clock.systemDefaultZone” name=“clock”/>
<bean id="timeTracker"
class="com.tracker.TimeTracker">
<constructor-arg ref=“clock”/>
</bean>
The value attribute is for primitive types only.
You need to instantiate a clock and use it as a reference. Something similar to:
<bean id="clock" class="java.time.clock"/>
<bean id="timeTracker"
class="com.tracker.TimeTracker">
<constructor-arg type="java.time.Clock" ref="clock"/>
</bean>
Try,
<bean id="timeTracker" class="com.tracker.TimeTracker">
<constructor-arg>
<bean class="java.time.Clock" factory-method="java.time.Clock.systemUTC" />
</constructor-arg>
</bean>
The solution from Strelok nearly works but it failed for me as you do not need to define the full path of the factory method. It is relative to the factory Class so if you type factory-method=“java.time.Clock.systemDefaultZone” it will look for a method in java.time.Clock.java.time.Clock.systemDefaultZone().
<bean id="systemClock" class="java.time.Clock" factory-method="systemUTC" />
<bean id="timeTracker" class="com.tracker.TimeTracker">
<constructor-arg type="java.time.Clock" ref="systemClock"/>
</bean>
To makes things worse the Spring exception is not especially helpful.
Strelok's answer almost works, it should be -
<bean name=“clock” class=“java.time.Clock” factory-method=“systemDefaultZone” />
I have a service class annotated with #Transactional calling a DAO layer method to return an object with a collection on it lazily loaded. When I then try and initialize this collection in the service layer using Hibernate.inititialize(..), hibernate doesn't load the collection. The DAO is configured to use entity manager and the object class is annotated with JPA annotations. I have the following spring application context..
<beans xmlns="http://www.springframework.org/schema/beans"...">
<orcl:pooling-datasource id="dataSource" url="..." username="..." password="..."/>
<context:annotation-config/>
<!-- Hibernate entity manager -->
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="org.gmp.webapp.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean id="dao" class="org.gmp.webapp.dao.impl.HibDAOImpl" />
</beans>
My DAO interface and implementaionn...
package org.gmp.webapp.dao;
import java.util.List;
import org.gmp.webapp.model.Crime;
public interface DAO {
public Crime getCrime(String crimeNo);
}
import org.gmp.webapp.dao.DAO;
import org.gmp.webapp.model.Crime;
public class HibDAOImpl implements DAO {
#PersistenceContext
protected EntityManager em;
public Crime getCrime(String crimeNo) {
return this.em.find(Crime.class, crimeNo);
}
}
My object looks something like this..
#Entity
#Table(name="CRIME_TABLE")
public class Crime {
#Id
#Column(name = "CRIME_NO")
private String crimeNo;
#OneToMany
#JoinColumn(name="PER_CRIME_NO", referencedColumnName="CRIME_NO")
private List<PersonCrimeLink> personLinks;
....
public List<PersonCrimeLink> getPersonLinks() {
return personLinks;
}
}
The service class is annotated with transactional (spring) so I thought as the call to the DAO and the initialize were in the same transaction, this should work.
My service..
#Service
#Transactional(readOnly=true)
public class CrimeServiceImpl implements CrimeService {
#Autowired private CrimeDAO crimeDAO;
public Crime getCrime(String crimeNo) {
Crime crime = crimeDAO.getCrime(crimeNo);
Hibernate.initialize(crime.getPersonLinks());
return crime;
}
}
The collection is loaded when I run a test of the DAO method, when making a call to the getter for the collection. I have annotated the test method with #Transactional. The personLinks object is omitted but like I say it returns the records in the test. I think I am not understanding the transaction manager I am using as this process worked when I was using session factory and HibernateTransactionManager.
Many Thanks in advance for any guidance on this.
Just a quick tip on this, as you decided to use the JPA's EntityManagerFactory instead of the Hibernate's SessionFactory as your orm API, then i would stick to that API on other layers of the application.
That is, using the EntityManager to get the data and then switch to using the implementation API (Hibernate.initialize) is not a consistent / maintainable approach.
Like you said in the post, if you stick to the JPA specification, which is initializing collection once it is accessed for the first time then you do not get any errors and the list is loaded:
The LAZY strategy is a hint to the persistence provider runtime that
data should be fetched lazily when it is first accessed
So as of JPA specification, you only need to do this:
public Crime getCrime(String crimeNo) {
Crime crime = crimeDAO.getCrime(crimeNo);
crime.getPersonLinks().size(); // any access method
return crime;
}
I have two class A and B . A is parent and B is child class.
am calling the class B methods.but class b accessing the methods of A.and i want to set a property in class A. So defined the property like
<bean name="b" class="com.dao.B" parent="parent">
<property name="utility" ref="utility"/>
</bean>
<bean class="com.dao.A" id="parent">
<property name="utility" ref="utility"/>
</bean>
and in the class A have a property named utility and with a setter...
when i try to get the instance i got null...
can u help me to set that
As A has a public setter of field utility then you can directly set property of object in class A from B like.
<bean name="b" class="com.dao.B">
<property name="utility" ref="utility"/>
</bean>
here utility is in class A with public setter and we are set value in B bean.
Do not use parent attribute, try this
<bean id="b" class="com.dao.B" >
<property name="utility" ref="utility"/>
</bean>
<bean id="a" class="com.dao.A">
<property name="utility" ref="utility"/>
</bean>
Is A a parent (in spring means) of B?
If not, just remove parent="parent" and id="parent" and you will be fine.
Read spring docs about abstract beans definition and use of parent.
I have the following XML configuration:
<bean id="bean1" class="Simple"/>
<bean id="bean2" class="Simple"/>
<bean id="tasks" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="bean1" />
<ref bean="bean2" />
</list>
</constructor-arg>
</bean>
<bean id="list" class="Comp">
<property name="tasks" ref="tasks"/>
</bean>
The "tasks" contains all beans of type Simple. The problem with this is that I might forget to add a Simple bean I've configured to the list.
I could do this programatically using
Map map = context.getBeansOfType(Simple.class);
and setting the list bean with the beans retrieved.
Is there any way of doing this using just XML configuration?
Your context file should like this:
<bean id="bean1" class="Simple"/>
<bean id="bean2" class="Simple"/>
<bean id="list" class="Comp" autowire="byType"/>
Note the autowire="byType" addition, and the autowiring documentation.
I would suggest writing your own FactoryBean for creating such a list. This would be reusable and then configurable using XML only. The FactoryBean would look like
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;
public class CollectingListFactoryBean implements FactoryBean, ApplicationContextAware {
private ApplicationContext appCtx;
private Class type;
public Object getObject() {
Assert.notNull(type, "type must be initialized");
List result = new ArrayList();
result.addAll(appCtx.getBeansOfType(type).values());
return result;
}
public Class getObjectType() {
return List.class;
}
public boolean isSingleton() {
return false;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.appCtx = applicationContext;
}
public void setType(Class type) {
this.type = type;
}
}
Then your XML configuration would be
<bean id="bean1" class="Simple"/>
<bean id="bean2" class="Simple"/>
<bean id="tasks" class="CollectingListFactoryBean">
<property name="type" value="Simple" />
</bean>
<bean id="list" class="Comp">
<property name="tasks" ref="tasks"/>
</bean>
NOTE: I didn't have the time to test the example above. I just used code I already had as a template. ;) Especially I'm not sure if passing Simple as a Class argument for the type property works this way. Just give it a try. In the worst case you would have to use String as the property type and use Class.forName(type) to get your class. But my guess is that Spring does this transformation for you.
EDIT Even though this solution should work, I recommend Robert Munteanu's answer.
I'd like to create a spring bean that holds the value of a double. Something like:
<bean id="doubleValue" value="3.7"/>
Declare it like this:
<bean id="doubleValue" class="java.lang.Double">
<constructor-arg index="0" value="3.7"/>
</bean>
And use like this:
<bean id="someOtherBean" ...>
<property name="value" ref="doubleValue"/>
</bean>
It's also worth noting that depending on your need defining your own bean may not be the best bet for you.
<util:constant static-field="org.example.Constants.FOO"/>
is a good way to access a constant value stored in a class and default binders also work very well for conversions e.g.
<bean class="Foo" p:doubleValue="123.00"/>
I've found myself replacing many of my beans in this manner, coupled with a properties file defining my values (for reuse purposes). What used to look like this
<bean id="d1" class="java.lang.Double">
<constructor-arg value="3.7"/>
</bean>
<bean id="foo" class="Foo">
<property name="doubleVal" ref="d1"/>
</bean>
gets refactored into this:
<bean
id="propertyFile"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:my.properties"
/>
<bean id="foo" class="Foo" p:doubleVal="${d1}"/>
Why don't you just use a Double? any reason?
Spring 2.5+
You can define bean like this in Java config:
#Configuration
public class BeanConfig {
#Bean
public Double doubleBean(){
return new Double(3.7);
}
}
You can use this bean like this in your program:
#Autowired
Double doubleBean;
public void printDouble(){
System.out.println(doubleBean); //sample usage
}