how to set SqlMapClientTemplate from spring xml - java

I've got following java class.
package com.org.data.dbresource;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
public class DBConnectionManager {
private SqlMapClientTemplate sqlMapClientTemplate;
public void setSqlMapClientTemplate (SqlMapClientTemplate sq)
{
this.sqlMapClientTemplate = sq;
}
public SqlMapClientTemplate getSqlMapClientTemplate ()
{
return this.sqlMapClientTemplate;
}
}
My Spring xml looks like following:
<bean id="IbatisDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/RSRC/app/oltp"/>
</bean>
<bean id="MySqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="classpath:sql-map.xml"/>
<property name="dataSource" ref="IbatisDataSource"/>
</bean>
<bean id="myObject" class="com.org.data.dbresource.DBConnectionManager">
<property name="sqlMapClientTemplate" ref="MySqlMapClient"/>
</bean>
Error I get is:
Failed to convert property value of
type
[com.ibatis.sqlmap.engine.impl.SqlMapClientImpl]
to required type
[org.springframework.orm.ibatis.SqlMapClientTemplate]
for property 'sqlMapClientTemplate';
Everything works fine if, instead of SqlMapClientTemplate I pass SqlMapClient but then I have to explicitly catch SQLExceptions
What should I change?

The error says it all - you're trying to inject an object of type SqlMapClient (as created by SqlMapClientFactoryBean) into a property of type SqlMapClientTemplate.
You need to manually instantiate the SqlMapClientTemplate yourself, either inside DBConnectionManager, e.g.
private SqlMapClientTemplate sqlMapClientTemplate;
public void setSqlMapClient(SqlMapClient sqlMapClient)
{
this.sqlMapClientTemplate = new SqlMapClientTemplate(sqlMapClient);
}
and then
<bean id="myObject" class="com.org.data.dbresource.DBConnectionManager">
<property name="sqlMapClient" ref="MySqlMapClient"/>
</bean>
Remember, SqlMapClientTemplate isw nothing more than a helper class. Neither Spring nor iBatis mandates its use, and if you want to use it, you need to instantiate it yourself.

Related

How to create java.util.Optional<T> object from Spring bean?

Java
public class MyObject{}
public class MyFactory{
private Optional<MyObject> myproperty;
public Optional<MyObject> getMyproperty{...}
public void setMyproperty{...}
}
Spring config xml (doesn't work)
<bean id="myproperty" class="java.util.Optional">
<constructor-arg>
<value>com.MyObject</value>
</constructor-arg>
</bean>
<bean id="myfactory" class="com.Myfactory">
<property name="myproperty" ref="myproperty" />
</bean>
Does spring support generics beans?
The reason for using Optional is it provide some useful features such as checking value if null. You can complete checking and further action in one line of code.
getMyproperty().ifPresent(id -> call.setId(id));
Seems the problem have nothing to do with generics.
You simply need to properly tell Spring to create the bean using a factory method, as Optional can only be created though factory methods. Something like:
<bean id="myproperty" class="java.util.Optional" factory-method="of">
<constructor-arg type="java.lang.Object" value="com.MyObject" />
</bean>
for which it is supposed to mean creating the myproperty bean by Optional.of(com.MyObject.class) (Change the factory-method to ofNullable if that's the one you want to use)
Another option is to use SpEL (Spring Expression Language):
<bean id="mybean" ...>
<property name="optProp" value="#{ T(java.util.Optional).of( #wrapme) }"/>
</bean>
Where "wrapme" is the name of a bean defined elsewhere that you want to wrap in java.util.Optional.

Replace JNDI lookup with mock object

I'm using jndi to perform a database lookup :
<jee:jndi-lookup id="myDataSource" jndi-name="jdbc/mydb"
resource-ref="true" expected-type="javax.sql.DataSource" />
In a spring context file I invoke the constructor using :
<bean id="myController " class="com.MyController">
<constructor-arg index="0" ref="myDataSource" />
</bean>
I no longer want to expose "myDataSource" via a jndi lookup, so a I create a mock object which is of same type as "javax.sql.DataSource" and use it instead as a constructor parameter :
<bean id="myMockDataSource" class="com.mock.MyMockDataSourceConnection">
</bean>
<bean id="myController" class="com.MyController">
<constructor-arg index="0" ref="myMockDataSource" />
</bean>
The mock object just returns a dummy connection.
Is this the correct way so as to longer use jndi lookup when want to use a mock object instead ?
You may want to look at Spring's SimpleNamingContextBuilder class, which is useful for building JNDI tree without needing a Java EE container.
class JndiMock
{
public void init()
{
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
builder.bind( "jdbc/mydb" , new YourDummyConnectionClass() );
builder.activate();
}
...
}
(This is from memory, but should give you the idea). You can instantiate it as a singleton right in your application context XML descriptor using the init-method attribute:
<bean id="jndimock" class="your.package.JndiMock" init-method="init" />
and make it is created before the jee:jndi-lookup.
Cheers,

Multiple Bean Instances in Spring

I was wondering if it is possible to specify x amount of the same bean in a list in Spring. For example, instead of having beans with ids: stage1, stage2,... stageN, as here:
<bean id="stage1" class="Stageclass"/>
<bean id="stage2" class="Stageclass"/>
<bean id="stages" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="stage1" />
<ref bean="stage2" />
</list>
</constructor-arg>
</bean>
Would it be possible to do something like the following?:
<bean id="stage1" class="Stageclass"/>
<bean id="stages" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="stage1" duplicate="20 times"/>
</list>
</constructor-arg>
</bean>
Thanks in advance.
If you use annotation based configuration and you specified list of objects with same interface as dependency for some class then spring will auto-wire aut-wire then for free. Example:
interface StageInterface {
//...
}
class StageImpl1 implements StageInterface {
//...
}
class StageImpl2 implements StageInterface {
//...
}
#Component
class StageContainer {
private final List<StageInterface> stages;
#Autowired
public StageContainer(List<StageInterface> stages) {
this.stages = stages;
}
public List<StageInterface> getStages() {
return stages;
}
}
This is a spring version 3+ feature.
I believe the same is possible with xml configuration as well. In your case that's probably will be the same class(StageClass), but with different configuration parameters.
Lookup method injection from http://static.springsource.org/spring/docs/2.5.x/reference/beans.html solved the problem. Just needed to make sure the bean I wanted multiple instances of had scope="prototype"
You can't do that using standard Spring's default namespace. However you can implement your own custom namespace where you could support such syntax.
Alternatively, you can implement a static method that would create an ArrayList instance with duplicated elements.

How to #Autowire a bean which is hidden behind ProxyFactoryBean?

Let's say we have two beans, defined in Spring
<bean class="foo.A"/>
<bean class="foo.B"/>
public class A {
#Autowired
private B b;
}
public class B {
public void foo() {
...
}
}
What I want to achieve is the interception of all calls to B.foo(). Looking at documentation, I wrote interceptor C and changed the definition of bean B as follows:
public class C implements org.springframework.aop.MethodBeforeAdvice {
public void before(final Method method, final Object[] args, final Object target) {
// interception logic goes here
}
}
<bean class="foo.C"/>
<bean class="org.springframework.aop.framework.ProxyFactoryBean" scope="prototype">
<property name="proxyTargetClass" value="true"/>
<property name="singleton" value="false"/>
<property name="target">
<bean class="foo.B" scope="prototype"/>
</property>
<property name="interceptorNames">
<list>
<value>foo.C</value>
</list>
</property>
</bean>
Problem: when starting up, Spring container complains: No matching bean of type [foo.B] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. In other words, it can't inject B into A because B is hidden behind org.springframework.aop.framework.ProxyFactoryBean and no longer "automagically" recognized. If I replace the definition into a simple class=foo.B, container starts fine. What's the best way to solve this?
Bonus question: is it possible to implement interception of B.foo() without involvement of ProxyFactoryBean and only using annotations (preferably without involvement of <aop:...)?
Define an interface for foo.B (e.g. foo.BInterface) and use foo.BInterface in the class A.
Also pay attention that Autowired injections are done only once. So if foo.A is singleton, it will receive only the first created instance of foo.B, while you want it to be a prototype.
Answer to bonus: Yes, but it may be more complicated. As a possible solution you can implement BeanPostProcessor. In the implementation you can replace the foo.B with dynamic proxy. So basically you do the same, but instead of using <aop: you do it yourself using basic Spring functionality. And again: you don't solve the "prototype is not autowired" problem and you still need an interface.
Perhaps you want to have the Bean 'foo.B' defined outside of the ProxyFactoryBean, and refer to it from the target property.
<bean class="foo.C"/>
<bean id="fooB" class="foo.B" scope="prototype"/>
<bean class="org.springframework.aop.framework.ProxyFactoryBean" scope="prototype">
<property name="proxyTargetClass" value="true"/>
<property name="singleton" value="false"/>
<property name="target" ref="fooB"/>
<property name="interceptorNames">
<list>
<value>foo.C</value>
</list>
</property>
</bean>
Tarlog's answer is correct, but to make it more clear:
you should wire objects by their interface, not by their class:
public class A {
#Autowired
private C b;
}
public class B implements C{
public void foo() {
...
}
}

Spring syntax for setting a Class object?

Is there a way to set a property in spring to, not an instance of a class, but the class object itself? i.e.
Rather than
<bean>
<property name="prototype" class="a.b.c.Foo">...
giving you an instance of "Foo", something like:
<bean>
<property name="prototype" class="java.lang.Class" value="a.b.c.Foo.class"...
edit:
best (working) solution so far - use the normal instantiation and derive the class in the setter. In terms of solutions I think this we'd describe this as "cheating":
<bean class="Bar">
<property name="prototype" class="a.b.c.Foo">...
public class Bar{
public void setPrototype(Object o){
this.prototypeClass=o.getClass();
edit:
dtsazza's method works as well.
edit:
pedromarce's method works as well.
<bean>
<property name="x">
<value type="java.lang.Class">a.b.c.Foo</value>
</property>
</bean>
That should work.
You could certainly use the static factory method Class.forName(), if there's no more elegant syntax (and I don't believe there is):
<property name="x">
<bean class="java.lang.Class" factory-method="forName">
<constructor-arg value="a.b.c.Foo"/>
</bean>
</property>
No. With a bean tag you instruct Spring on how to instantiate a class.
Would <property name="x" class="a.b.c.Foo.class"> work? That should be an instance of a Class object...

Categories