Wiring Database Object with Spring Bean - java

From Spring in Action book, there is an example of Spring Bean. It uses Compact Disc analogy. When an application needs a "The Beatles" album, it creates "The Beatles" album bean, and as well as other albums.
If there are n albums in database, so should I create n album beans?
If it is not, how the n albums represented in application? Is it just a POJO domain model (not a bean)?
What is the real use case using Spring Bean?

If I were you, I would depart from the analogy of the compact disc as a Spring bean, especially with respect to your later questions. Quite plainly, any Java object can be declared as a bean in Spring, whether you're using XML configuration or Java configuration.
Let's suppose I have these 2 classes:
public class Foo {
private String s;
private Bar bar;
// getters & setters
}
public class Bar {
private int i;
// getter & setter
}
I can make the former a Spring Bean by declaring it in an XML configuration file:
<bean id="foo" class="demo.Foo">
<property name="s" value="Hello, World!" />
<property name="bar">
<bean class="demo.Bar">
<property name="i" value="10" />
</bean>
</property>
</bean>
Now, with these 2 lines of code:
ApplicationContext ctx = new ClassPathXmlApplicationContext("app.xml");
Foo foo = ctx.getBean(Foo.class);
The foo object that was configured can be retrieved, and all its properties including bar will be set. This is the core use case of Spring, i.e. letting you configure how the building blocks of your application resolve their dependencies at runtime. Initially Spring was all about configuration outside of code, but the focus now has slightly changed, with things like component scans and Java configuration...
Anyway, to conclude with this brief example, the following line of code will print 10:
System.out.println(foo.getBar().getI());
In this example, I took Foo and Bar, but it could as well be a Web Service, a service implementing some business logic, a database, an ORM facade, a template engine, a thread pool, anything... But mostly components dealing with data objects, not data objects themselves, though this is entirely possible.
Now to return with your use case, in a Spring app, I would generally have these components if I'm coding a Web app with a database: a controller (the Web boundary), a service (for business logic), a repository (for querying) and of course a data source. I won't delve into too much details here (no declarative transactions for example). Notice that with this configuration, no specific data provider is compiled into my Java code, it remains in the configuration:
<bean id="cdController" class="demo.compactdisc.CdController">
<property name="cdService" ref="cdService" />
</bean>
<bean id="cdService" class="demo.compactdisc.CdServiceImpl">
<property name="cdRepository" ref="cdRepository" />
</bean>
<bean id="cdRepository" class="demo.compactdisc.CdRepositoryImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="test"/>
<property name="password" value="s3cr3t"/>
</bean>
With your domain, the repository would return the compact discs from the database to the service, the service to the controller and the controller to the user. Compact discs would not be described as Spring beans but would certainly be parameters and return values from the actual Spring beans.

You just need to have one Album class and annotate it as a #Component or do it via xml.
The terms bean and POJO are interchangeable. As per Spring in action 4rd edition, Spring tries hard to be a non-invasive framework.
(...)the classes in a Spring-based application often have no
indication that they’re being used by Spring. At worst, a class may be annotated with one of Spring’s annotations, but it’s otherwise a POJO
and
Although Spring uses the words bean and JavaBean liberally
when referring to application components, this doesn’t mean a Spring component
must follow the JavaBeans specification to the letter. A Spring component can be
any type of POJO.
The use case is that you can use the Spring Dependency Injection to wire your beans on run-time, your application can benefit from Spring in terms of simplicity, testability, and loose coupling.
In short, a Spring bean as you refer is just a POJO used in the context of an Spring Application. If you use the xml mapping instead of the annotation, your class will be just another regular Java class, a Plain Old Java Object.

If there are n albums in database, so should I create n album beans?
I would think not. If there are n albums it would be very cumbersome to include them all explicitly in your App.config file if that's what you're referring to; but you could. You would probably add an AlbumService (#Service) #Bean and associated #Repository to handle writing and retrieving them from the DB.
If it is not, how the n albums represented in application? Is it just
a POJO domain model (not a bean)?
You could have an Album #Entity bean with the attributes of an album. When you save an album you'd set the attributes as opposed to having individual components implementing a common interface. Your DB would have n albums in it. If you needed to retrieve just one Beatles album you could query based on the album title, for example. If you wanted them all you could do albumService.findAll(); and get a container of them.
What is the real use case using Spring Bean?
Spring is the real use case of a Spring Bean. According to the Spring IoC Container Reference:
In Spring, the objects that form the backbone of your application and
that are managed by the Spring IoC container are called beans. A bean
is an object that is instantiated, assembled, and otherwise managed by
a Spring IoC container. Otherwise, a bean is simply one of many
objects in your application. Beans, and the dependencies among them,
are reflected in the configuration metadata used by a container.
I can't provide a better answer than what's contained in the documentation or given in this answer.

Related

spring 3: inject a dependency from a library?

I am developing a project and using 3rd party libraries. Let's say I use a library which gives me the object ExtObj. In my project I have a class MyObj, which uses ExtObj. How can I configure spring 3 to inject ExtObj in MyObj?
I tried to research the topic on the internet, but I didn't find a straight answer. I would like to use xml configuration and maybe (?) #Autowired, not #EJB or #Inject
Thanks in advance!
UPDATE
my guess was:
<bean id="myObj" value="me.MyObj">
<property name="extObj" value=" ... ??? ...">
</bean>
So, I don't know what I should put into value. I guess that's where the reference to the external object goes. But spring can only reference objects that have been already defined/configured in spring. So:
<bean id="extObj" value="ext.lib.ExtObj">
<bean id="myObj" value="me.MyObj">
<property name="extObj" value="extObj">
</bean>
Is that configuration right?
First you need to define a bean for your ExtObj in your application context (an xml file or a #Configuration class). Eg. if ExtObj has a constructor taking a String you can define the bean this way:
<bean id="extObj" class="ext.lib.ExtObj">
<constructor-arg value="SomeString"/>
</bean>
To define MyObj you can use constructor injection:
<bean id="myObj" class="me.MyObj">
<constructor-arg ref="extObj"/>
</bean>
or setter injection:
<bean name="myObj" class="me.MyObj">
<property name="extObj" ref="extObj"/>
</beans>
If you use setter injection then MyObj needs to have a setter setExtObj. If you use constructor injection MyObj needs to have a constructor taking an instance of the ExtObj class.
Of course you can inject a 3rd party library, as long as it has constructors that Spring can access.
You can use either XML or annotations - your choice.
You need to ask Spring to instantiate the instance(s) of the library class and then inject that into your objects that need them.
You do this every time you create a Spring data source that uses a JDBC driver. That's a 3rd party library.

Spring injecting one property dynamically

I am new to Spring and i am stuck with a scenario where i need help.
My Scenario is i have a bean definition for some specific module like this.
<bean name="ruleEngineAction" class="com.xxxxx.yyyy.UserAction" scope="prototype">
<property name="userManager">
<ref bean="userManager" />
</property>
<property name="userDto">
<ref bean="userDto" />
</property>
</bean>
now within this bean i want to use one more property but that depends on the application flow like
<property name="roleManager">
<ref bean="roleManager">
</property>
so should i include this property with in the bean definition itself or i can do it dynamically in code because i don't want this property to be used a lot.
Please suggest me the right and efficient approach.
From what I understood from question, there is only one bean of type roleManager but the usage of roleManager is based on application flow.
In this scenario, I would recommend you to inject roleManager to ruleEngineAction as you would do with any other bean but use the bean only when it is necessary.
It is a bad practice to needless dependency to spring in normal classes like adding reference to applicationContext for fetching the bean dynamically at runtime.
Whether or not, you inject this bean, it'll anyways be created by Spring. Why not just include the property in your UserAction and whether to use it or not, can be decided in your class. No harm in having the bean injected, because you'll anyways use it for some scenarios.
Had the scenario been like, the object won't be created, if you don't inject/use, then it would make sense to consider this situation, but since Spring will create the object anyways, it really shouldn't be a problem to just inject it.
Well you need to add new property with getter and setter in your class com.xxxxx.yyyy.UserAction for roleManager like :
class UserAction {
// your previous properties userManager, userDto, etc.
private RoleManager roleManager; // assuming interface/class as RoleManager for roleManager
// getter and setter for roleManager
// your other action methods which will use roleManager
}
There is no problem if you inject also.Whenever you access that class only it will create the object of that class.

Switch between two beans in spring

I have two beans which comes from the same class(id1 and id2), the difference is ids and some properties.
In the code, I called getbean(id1) to get the object.
How can I switch to id2 without recompiling the code?
If you have two different beans wit different properties that means you have two different objects. That means you treat them as you would normally treat different objects -
BeanClass b1 = (BeanClass) ctx.getBean("id1");
BeanClass b2 = (BeanClass) ctx.getBean("id2");
However if you have a seperate scenerio where you load bean 1 in your class for normal working and bean 2 in your class when you run it via JUnit then you should have a different approach altogether -
Have two different applicationContext.xml files. First one loads when your code runs and then other(applicationContext-test.xml) is loaded when you are running your code via JUNIT. This way you can load different beans without changing the code.
It doesn't seems good design,
Spring are generally service beans, you should have only one implementation object of Bean.
well then also if you want to do it.
then read the bean ID from Properties file while fetching bean.
From your question, I'm assuming that you want to switch between bean instances programatically....
Given the following setup:
<bean id="instance1" class="my.bean.A">
<property name="property_B">
<ref local="B"/>
</property>
</bean>
<bean id="instance2" class="my.bean.A">
<property name="property_B">
<ref local="B"/>
</property>
</bean>
then in your code, you can switch between the two using the ApplicationContext... (This is Spring 2.x code)
ApplicationContext ctx = new FileSystemXmlApplicationContext(
"my-XML-Config-File-Above.xml");
A instance1 = (A) ctx.getBean("instance1");
A instance2 = (A) ctx.getBean("instance2");

Can spring container inject collaborators using custom methods?

Normally dependencies are injected via setters by the following configuration (http://static.springsource.org/sprin...beans-beanname) :
<bean id="exampleBean" class="examples.ExampleBean">
<!-- setter injection using the nested <ref/> element -->
<property name="beanOne"><ref bean="anotherExampleBean"/></property>
<!-- setter injection using the neater 'ref' attribute -->
<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
Lets say the class examples.ExampleBean has a collection listeners objects, and the method addListener(SomeListenerInterface) is the only possible way add listeners. Can I inject listeners declaratively in xml like its done with property setters?
You could probably conjure up some baroque mechanism for doing this all in XML, but the cleanest way to do this is to use a FactoryBean. You write a class which implement FactoryBean, and which is responsible for constructing and configuring your target object (see Spring docs). Your FactoryBean would have the required getters/setters/autowiring, and injects them into the target object.
This is often the cleanest way to handle non-javabeans in Spring, particularly if you cannot modify the target class.
Here goes property Element definition
Property elements correspond to JavaBean setter methods exposed by the bean classes.
To get your goal, you can use #Autowired annotation. It works even when using an arbitrary name
#Autowired
public void inject(SomeListenerInterface someListenerInterface) {
this.someListenerInterface = someListenerInterface;
}

Swappable data layer using spring ioc

I have DAO's for each table, that all implement an interface.
Now I want to be able to (potentially) swap database layer implementations.
So my strategy is to create a DaoFactory, and this DaoFactory will be specific to a particular implemenation of my DAO's.
So I will have DAO's for hibernate.
Then a DaoHibernateFactory that will look like:
public class DaoHibernateFactory implements DaoFactory
{
public UserDao GetUserDao() {
return new UserHibernateDao();
}
}
Then in all my manager/service classes, I will use whichever Dao___Factory is currently wired via spring ioc.
Does this make sense? Suggestions?
I would have separate configuration files for each implementation, rather than using factories. That way spring can inject your DAOs for you, and you don't have to call or maintain an extra factory class.
For example:
hibernate-data.xml:
<bean id="userDAO" class="com.foo.dao.hibernate.HibernateUserDao">
...
</bean>
ibatis-data.xml:
<bean id="userDAO" class="com.foo.dao.ibatis.IBatisUserDao">
...
</bean>
etc.
Then you can swap out the implementation by changing which -data file is included in your web.xml.
Since you are using dependency injection, you should try to use the wiring that is provided out of the box from the DI framework in question rather than writing your own factories.
The current problem can be solved using SpringPropertyPlaceHolder and a simple convention around the naming of the DAOs in the spring configuration file.
Steps:
1. First use some naming convention to name the Ids of your individual DAOs and configure them in the spring file.
Ex:
<bean id='hibernateUserDao' class='UserHibernateDao'/>
<bean id='ibatisUserDao' class='UserIbatisDao'/>
Here we are saying that all Hibernate Daos begin with hibernate and all ibatis Daos begin with ibatis etc.
2.Next configure the consumer of the Daos. Make sure that the wiring is dynamic depending on properties.
<bean id='daoconsumer' class='some.consumer.class'>
<property name='dao' ref='${daoImpl}UserDao'/>
</bean>
3.After that configure Spring Property place holder in your spring file.
<bean id="propertyConfigurator" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:/path/to/app.properties</value>
</property>
</bean>
4.Finally you write the app.properties with the single line.
daoImpl=hibernate # choose hibernate implementations.
Now, the daoImpl would get replaced by "hibernate". The other advantage of this technique is that SpringPropertyPlaceHolder can also obtain properties from the environment which it can use in preference to the app.properties (depends on a configuration parameter look up the javadocs for details)
Hence you can configure your app behavior using environment properties as well which can be pretty powerful.
Alternative 2:
You can also use Maven Profiles to achieve similar behavior. Maven has the ability to "filter" your resources - in this case it would replace placeholders with some strings depending on the maven profile that it is executing under. You can leverage this feature to generate app packages (jars, ears etc.) that work with a given implementation (like hibernate,ibatis etc). Obviously, this is less flexible than the PropertyPlaceHolder approach but can be preferable under certain conditions.
I would say you're missing the point badly if you think you need to write a factory. The Spring application context is the factory in this case: a declarative, dynamic object factory. The classes that use your factory lose the advantage of Spring.
You could write a generic DAO so you don't have to maintain all that code.
package hibernate.policy.persistence;
import java.io.Serializable;
import java.util.List;
public interface GenericDao<T, K extends Serializable>
{
T find(K id);
List<T> find();
List<T> find(T example);
List<T> find(String queryName, String [] paramNames, Object [] bindValues);
K save(T instance);
void update(T instance);
void delete(T instance);
}

Categories