Spring bean constructor-arg - spring

<?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-4.0.xsd"
default-autowire="byName">
<bean name="schedulerMap" class="java.util.HashMap">
<constructor-arg>
<map>
<entry key="moBiScheduler" value-ref="moBiScheduler"/>
<entry key="billJobScheduler" value-ref="billJobScheduler"/>
</map>
</constructor-arg>
</bean>
</beans>
That's some of the XML.
In the class, I want to use #Autowired to inject the value of key='moBiScheduler' and key='billJobScheduler'
#Autowired
private Map<String, Scheduler> schedulerMap;

It's possible , you can
autoriwre a method that takes Map and do some filtering and put the right values to schedulerMap
Create another class MapHolder which extends Map (it's optional) and implements ApplicationContextAware. after the injection of ApplicationContext you can retrieve schedulerMap and do some filtering and put the right value to your map , then inject this map
you can also use BeanPostProcessor

Related

Creating a repository instance in Spring Data

I'm new to Spring Data and to Spring in general, so don't be hard on me.
I can't find a way to instantiate a repository. I read the documentation:
http://docs.spring.io/spring-data/data-solr/docs/1.0.0.RC1/reference/htmlsingle/#repositories.create-instances
It describes different ways of declaring repositories (xml, filters, etc), but doesn't say how I can get an instance of it in my code.
Here is my configuration xml file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:solr="http://www.springframework.org/schema/data/solr"
xsi:schemaLocation="http://www.springframework.org/schema/data/solr http://www.springframework.org/schema/data/solr/spring-solr-1.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<solr:repositories base-package="spring" />
<solr:solr-server id="solrServer" url="http://localhost:8983/solr" />
<bean id="taskRepo" class="spring.SolrTaskRepository">
</bean>
<bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate">
<constructor-arg index="0" ref="solrServer"/>
</bean>
</beans>
And SolrTaskRepository:
public interface SolrTaskRepository<T, ID extends Serializable> extends SolrCrudRepository<T, ID> {
Page<T> findByOrigin(String origin, Pageable page);
}
Could someone help me out?
If you want to use the repo(or any spring bean) somewhere out of the context:
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
MyRepo obj = (MyRepo) context.getBean("myRepo");
If you use the repo in some other bean managed by spring(some service) you can autowire it
#Autowire
private MyRepo myRepo;// + setter
or inject it in the context:
<bean id="someService" class="com.org.core.SomeService">
<property name="myRepo" ref="myRepo" />
</bean>
For both ways you need the bean defined in the context:
<bean id="myRepo" class="com.org.core.MyRepo">
</bean>
Example context file:
<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-2.5.xsd">
<bean id="myRepo" class="com.org.core.MyRepo">
</bean>
</beans>
IF you load the context with ClassPathXmlApplicationContext you need the file in the classpath.

Injecting bean declared in xml file using the #Inject annotation

I can't get #Inject to work properly. I'm trying to inject a bean from xml using the #Inject annotation, but I get the error message
"java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required".
I have also been trying in combination with #Qualifier("dataSource"), but wherever I put the #Qualifier it says "The annotation #Qualifier is disallowed for this location".
I have been reading loads of documentation on #Inject and I can't seem to find anything that mentions any special treatment of beans declared in xml.
However, I'm guessing Spring is trying to create the FooDaoImpl bean before scanning the dataSourceBean.
How would I go about using #Inject to inject the dataSource bean declared in the xml file?
Is it even possible, using #Inject?
FooDaoImpl.java
#Repository
public class FooDaoImpl extends NamedParameterJdbcDaoSupport implements FooDao {
#Inject
private DataSource dataSource;
DSLContext create = DSL.using(dataSource, SQLDialect.DB2);
}
Spring-Module.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" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="com.example.foobar" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.ibm.db2.jcc.DB2Driver" />
<property name="jdbcUrl" value="jdbc:db2://localhost:50000/BLABLA" />
<property name="user" value="PAPAYA" />
<property name="password" value="COCONUT" />
</bean>
Cheers!
This works fine in Spring. I use the #Autowired annotation, not #Inject.
I managed to use #Inject to inject the dataSource to my Dao. I used a #PostConstruct to achieve this, like so:
#Inject
private DataSource dataSource;
#PostConstruct
private void initialize(){
setDataSource(dataSource);
}
DSLContext create = DSL.using(dataSource, SQLDialect.DB2);
I'm sure there is a better, or "cleaner" way of achieving this, but none that I could find.
Thanks for your suggestions!
To get rid of the The annotation #Qualifier is disallowed for this location message you have to use the annotation #interface.

#Autowired doesn't work if component-scan removed

I'm facing the problem, that the annotation #Autowired doesn't work anymore (in all Java classes that uses this annotation) if I remove the component-scan tag from config
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="efco.auth" />
here are some beans...
There is only one class in the efco.auth package, and this one has no relation to the following class EfcoBasketLogic.
and a class that uses #Autowired:
package efco.logic;
public class EfcoBasketLogic extends BasketLogicImpl {
#Autowired
private EfcoErpService erpService;
This Bean is defined in an other spring config file:
<bean id="BasketLogic" class="efco.logic.EfcoBasketLogic">
<property name="documentLogic" ref="DocumentLogic" />
<property name="stateAccess" ref="StateAccess" />
<property name="contextAccess" ref="ContextAccess" />
</bean>
As you can see, erpService is not defined. The other three properties are on BasketLogicImpl and have setters.
What I'm doing wrong?
As Tomasz says, you need <context:annotation-config/> for #Autowired to work. When you had <context:component-scan/>, it implicitly included annotation-config for you.
Adding either autowire="byType" or autowire="byName" to your bean declaration should do the job.

Using Morphia with Spring

The Google Code site of Morphia says it "works great with Guice, Spring, and other DI frameworks."
I'm learning Spring at the moment, so i'm just experimenting with connecting these two tools.
I've created a User POJO to store user objects with Morphia in MongoDB. I've also created a UserDAO class extending BasicDAO from Morphia to access objects.
My Spring application context configuration XML looks like this:
<?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-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
xmlns:aop="http://www.springframework.org/schema/aop">
<bean class="java.lang.String" id="mongoDb">
<constructor-arg value="test"/>
</bean>
<bean class="com.google.code.morphia.Morphia" id="morphia" />
<bean class="com.mongodb.Mongo" id="mongo"/>
<bean class="hu.inagy.testspring.daos.UserDAO" id="userDao">
<constructor-arg ref="morphia" index="0" />
<constructor-arg ref="mongo" index="1" />
<constructor-arg ref="mongoDb" index="2" />
</bean>
</beans>
I have a simple main class to test functionality:
public class App
{
public static void main( String[] args )
{
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/app-context.xml");
UserDAO userDao = (UserDAO) applicationContext.getBean("userDao");
userDao.deleteByQuery(userDao.createQuery());
User user = new User();
user.setName("Test");
userDao.save(user);
User ret = userDao.find().get();
System.out.println("Saved user is: "+ret);
}
}
This works fine, however i don't know if i did everything as it should be. For example i haven't called ensureIndexes() and ensureCaps() on the datastore. My code also doesn't have an explicit mapping call for the POJOs on the Morphia object.
Are these done for me automatically or should i do other things to use Morphia correctly with Spring?
I don't use spring but this articles seems to talk about exactly what you need, a hook to do things when you app starts: http://leshazlewood.com/2007/07/30/spring-application-bootstrap-data/
You can do the Datastore.ensureIndexes/Caps() there.
You can also read this thread about using #Autowire and annotations instead of the xml, if you like that stuff.
http://groups.google.com/group/morphia/browse_thread/thread/1013b17963f29468

Spring - using static final fields (constants) for bean initialization

is it possible to define a bean with the use of static final fields of CoreProtocolPNames class like this:
<bean id="httpParamBean" class="org.apache.http.params.HttpProtocolParamBean">
<constructor-arg ref="httpParams"/>
<property name="httpElementCharset" value="CoreProtocolPNames.HTTP_ELEMENT_CHARSET" />
<property name="version" value="CoreProtocolPNames.PROTOCOL_VERSION">
</bean>
public interface CoreProtocolPNames {
public static final String PROTOCOL_VERSION = "http.protocol.version";
public static final String HTTP_ELEMENT_CHARSET = "http.protocol.element-charset";
}
If it is possible, what is the best way of doing this ?
Something like this (Spring 2.5)
<bean id="foo" class="Bar">
<property name="myValue">
<util:constant static-field="java.lang.Integer.MAX_VALUE"/>
</property>
</bean>
Where util namespace is from xmlns:util="http://www.springframework.org/schema/util"
But for Spring 3, it would be cleaner to use the #Value annotation and the expression language. Which looks like this:
public class Bar {
#Value("T(java.lang.Integer).MAX_VALUE")
private Integer myValue;
}
Or, as an alternative, using Spring EL directly in XML:
<bean id="foo1" class="Foo" p:someOrgValue="#{T(org.example.Bar).myValue}"/>
This has the additional advantage of working with namespace configuration:
<tx:annotation-driven order="#{T(org.example.Bar).myValue}"/>
don't forget to specify the schema location..
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
</beans>
One more example to add for the instance above. This is how you can use a static constant in a bean using Spring.
<bean id="foo1" class="Foo">
<property name="someOrgValue">
<util:constant static-field="org.example.Bar.myValue"/>
</property>
</bean>
package org.example;
public class Bar {
public static String myValue = "SOME_CONSTANT";
}
package someorg.example;
public class Foo {
String someOrgValue;
foo(String value){
this.someOrgValue = value;
}
}
<util:constant id="MANAGER"
static-field="EmployeeDTO.MANAGER" />
<util:constant id="DIRECTOR"
static-field="EmployeeDTO.DIRECTOR" />
<!-- Use the static final bean constants here -->
<bean name="employeeTypeWrapper" class="ClassName">
<property name="manager" ref="MANAGER" />
<property name="director" ref="DIRECTOR" />
</bean>

Resources