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);
}
Related
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.
One of the Spring features I like the most is how you can handle properties loaded from a file. You only to need to set up a bean like the one below
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
Now you are able to inject the properties values loaded from the app.properties into your beans by using either xml (see below) or annotations.
<bean class="com.example.PersonDaoImpl">
<property name="maxResults" value="${results.max}"/>
</bean>
results.max is one of the properties.
I'm great fan of this feature because it enables me to create quite flexible applications that I can turn on/off some functionality by only changing one property - without redeploying the app.
Now I'm working with JBoss Seam and I've been struggling to find a way to do something similar using this framework.
Does anyone know how to do it? If not, does anyone have any idea of how I could handle properties in a nice way using Seam (I have seen some ways - but none of them were good enough).
Thanks.
If there's no appropriate way using you software stack (is there really no dependency injection!?). I'd say: Use Google Guice (https://code.google.com/p/google-guice/ , https://code.google.com/p/google-guice/wiki/Motivation?tm=6)!
Bad thing with Guice: You may have to read a lot to understand how it works, and what you can do with it. But after it's running you will simply inject your Properties object where you need it:
class YourClass {
#Inject Properties myProperties;
#Inject
public YourClass() { ... }
public void someMethod() {
use the property
}
}
or if you need the properties inside the constructor, you could also do:
class YourClass {
final Properties myProperties;
#Inject
public YourClass(Properties myProperties) {
this.myProperties = myProperties;
}
public void someMethod() {
use the property
}
}
Using Guice maybe enforces you to refactor your whole app.
But if you already have some DI framework, you should simply use that :)
I have a system where I have an enum of Shops for example. These shows each have their own ShopCommand property (some of which share the same type of command class). from a method in the command class I then want to call send on a Spring Integration gateway. Where I'm confused is how to actually insantiate this gateway in spring. Ideally what I want is to construct the enum via XML configuration with command property being created also in spring, which has the property outGateway set via Spring. I'm not sure if I've made myself very clear with this descrition, if clarification is needed then just ask!
I think this is what you are asking for:
Say I have an enum for ShopType
public enum ShopType {
GROCERY, DEPARTMENT, MALL;
}
Then I have some Store bean that I want to setup via spring configuration. You can instantiate and use the enum like this:
<bean id="DEPTARTMENT_STORE" class="my.package.ShopType" factory-method="valueOf">
<constructor-arg value="DEPARTMENT"/>
</bean>
<bean id="searsStore" class="my.package.Store">
<property name="shopType" ref="DEPTARTMENT_STORE"/>
</bean>
The factory-method points to a static method that is used to create the object. So you can use the enum's method "valueOf" as a factory method.
I'm trying to setup mocked object (using Mockito) via spring bean configuration, however I don't know how to setup MockSettings for that object. Especially I would like to set up object serializable.
Programatically it is possible by:
Object serializableMock = mock(Object.class, withSettings().serializable());
<bean id="object" name="object" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="object" />
<constructor-arg value="org.mockito.MockSettings"> ??? </constructor-arg>
</bean>
Can somebody guide me how to do that ? Thanks in advance
BTW : I want to use pure XML configuration.
Only via XML, you can't.
Actually I wouldn't recommend you to have the usual practice of using Mockito mocks in spring for tests. Here's why :
Usually when Unit Testing, you want to test one class in isolation, it's unit testing after all, so Spring DI isn't necessary at all in this case. You just inject the collaborators of your test subject yourself or maybe via the handy #InjectMock annotation.
If however you need to test things with another system like a DAO with a Database, then indeed you probably need Spring wiring to connect to either the real DB or some in memory DB like H2. But in this case you are crafting an Integration Test. And you most probably don't need mocks in this case.
That said, you might have specific needs and the above point could be irrelevant in your specific bounded context. But then again, in my opinion if it's specific I don't think it's overkill to craft yourself a simple MockSettings factory bean (that could even be configurable).
E.g. you could write this once and for all in a technical module of your application :
public class SpringMockSettingsFactoryBean extends AbstractFactoryBean<MockSettings> {
#Override public Class<Multimap> getObjectType() {
return MockSettings.class;
}
#Override protected Multimap<String, String> createInstance() throws Exception {
// ... your code
return mockSettings;
}
}
There's a project springockito on bitbucket that tries to have a mockito focused namespace in spring. I don't think the project can do that, but the framework's author might be interested to implement the feature.
Hope that helps.
yes, you can do it via XML
<bean id="mockSettings" class="org.mockito.Mockito" factory-method="withSettings" init- method="verboseLogging">
</bean>
<bean id="sqsHelper" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.elsevier.vtw.aws.helper.SQSHelper"/>
<constructor-arg ref="mockSettings" />
</bean>
I read about Compound property names in the "The Spring Framework (2.5) - Reference Documentation - chapter 3.3.2.7"
Can i use the same concept to set values of properties? Can i use a compound string as a value expression?
<bean id="service1" class="a.b.c.Service1Impl" scope="prototype">
<property name="service2" ref="service2"/>
<property name="service2.user" value="this-service1-instance.user"/>
</bean>
<bean id="service2" class="a.b.c.Service2Impl" scope="prototype">
...
</bean>
User is a property of a.b.c.Service1Impl which is not in control of Spring. I want to forward this property to a.b.c.Service2Impl.
Rather than use a plain old factory bean, rather use a factory method to create the bean of the property and then inject that result...
iow
in your case, it would look something like this...
<!-- the bean to be created via the factory bean -->
<bean id="exampleBean"
factory-bean="serviceLocator"
factory-method="createInstance"/>
So the bean of id is created by calling createInstance on bean serviceLocator.
Now spring does not support nested properties out of the box, though you could look at creating a custom editors which might provide that support - possible but tricky. Possibly not worth the effort.
One mechanism you could look at using is nesting using the factory-bean factory-method technique...
Something like:
<bean id="c" class="C" />
<bean id="b" factory-bean="c" factory-method="getB"/>
<bean id="a" factory-bean="b" factory-method="getA"/>
This will effectively expose: a.b.c where C has a method getB and A has a method getB
I had to do something similar, and I'm afraid it's not possible. I had to write a [FactoryBean][1] to expose the property.
It would look something like this:
public class UserFactory implements BeanFactory {
private Service2 service2;
// ... setter and getter for service2
public Object getObject() {
return getService2().getUser();
}
public Class getObjectType() {
return User.class;
}
public boolean isSingleton() {
// Since it's a prototype in your case
return false;
}
}
Come to think of it, in your case, you'd probably define the factory itself as a prototype, in which case your isSingleton() may return true, you'll need to play around with this a little bit.
Spring's XML wiring syntax supports lists, maps and properties objects, and you can create other 'data' objects via property editors.
Edit: (Oh I see what you are asking.) I think that the answer is no. I don't recall having seen any mention of calling getters on a bean or non-bean object in the Spring documentation, let alone a syntax for doing this in the wiring file. It tends to go against the grain. Spring wiring is declarative, and calling a getter would lead to patterns that are bordering on procedural.