Abstract class variable with spring - java

I am using spring and Hibernate and Dao design pattern for the my project, In my GenericDaoImpl(Abstract class) class has "tenentId", I want to set the "tenentId" when use login to the System. My other DaoImpl classes extends from GenericDaoImpl, so I need to set the tenentId(It's define in GenericDaoImpl) user login time and reset the "tenentId" when user log out.
What is the best way to do this?
In my test cases I tried #Autowired the "GenericDaoImpl" but I couldn't do that, It throws an exception telling, org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type. I know the problem now,
(We can't create instance of abstract classes,if use tenantId as static variable, is it going to be a problem?)
Can any one suggest me any solution?
Thank you,
Udeshika

if you are developing multi-tenancy application and would like to have tenant aware application context then have a look spring-tenancy. This will help you to have beans injected which are tenant aware.
if you want to multi-tenancy at hibernate layer then you can also look at multi-tenancy feature of hibernate.

Related

Using different DataBases with Spring jdbcDaoSupport

Which is the best approach to implement several different databases in one project, using Spring JdbcDaoSupport?
I have several DB with different datasources and syntax: MySQL & Postgres, for example. In pure java-jdbc projects i used Factory Method and Abstract Factory patterns, and multiple DAOimpl classes (one for each DB) with common DAO interfaces for switch between databases. Now i use Spring-jdbc and want to implement similar behavior.
I faced the same matter two year ago and I finally choose an implementation based on a "Spring Custom Scope" (http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-scopes-custom).
The spring frameworks allows multiple instances of the same bean definition to coexists together. They differ only from some contextual settings.
For instance, this bean definition will create various loginAction bean depending on the currently processed HTTP request
<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>
If you create a custom scope called "domain", you will be able to instanciate several datasource based on the same bean definition.
A datasource bean definition based on JndiObjectFactoryBean would let the servlet container manage the database connection (through the web.xml file). However, you would have to variabilize your datasource name with a Spring Property.
Beans like the database Transaction Manager must also be marked with this scope.
Next you need to activate the scope each time an HTTP request is running: I can suggest you to define the datasource name as a prefix of the request url.
Because most of web frameworks allows you to intercept HTTP requests, you can retrieve the expected datasource before processing the request.
Then, create (or reuse) a set of beans specific to the selected datasource and store it inside a ThreadLocal variable (that your custom scope implementation will rely on)
This implementation should look a little complex at first glance, but its usage appears transparent.

#SpringBean support for bean in child ApplicationContext

I'm working with the developer of PF4J(Plugin Framework for Java) to provide better plugin functionality for Wicket. There is already a pf4j-spring and a pf4j-wicket project to provide some basic integration. In order to allow the #SpringBean or #Inject annotations to have access to plugin beans in a child context we need to be able to lookup the ApplicationContext associated with a specific class.
So for example, say I have a MyService bean in a child(plugin) ApplicationContext and that plugin also provides a panel that needs that via a #SpringBean annotation. Spring doesn't allow the parent ApplicationContext to see beans in a child context and for good reason. So we would get an exception saying that bean could not be found since #SpringBean only looks up beans in the parent context. We have code that we have developed that look up the child context like so:
SpringPlugin plugin = (SpringPlugin)PluginManager.whichPlugin(MyService.class);
ApplicationContext pluginContext = plugin.getApplicationContext();
How could I modify or provide this functionality in a custom version of SpringComponentInjector? It uses a ISpringContextLocator but that context locator does not specify the class for which it needs the ApplicationContext.
Any ideas on how this could be achieved?
Thanks for your help!
I'm afraid current SpringComponentInjector is not prepared for such usage. You will have to create your own version.
The problem that I see is that you will have to have either as many IComponentInstantiationListeners as plugins there are. Or create a composite ICIL that delegates to SpringBeanLocators for each plugin. I think the composite would be better. Then you'll have to make sure that a Panel in pluginA cannot use a bean located by SpringBeanLocatorB.
If you manage to do it and you find something in wicket-spring that could be made more generic to help make your version simpler then please let us know and we will consider your suggestion(s)!
Take a look at sbp. It is built on top of pf4j to support Spring Boot, and also provides mechanism of sharing beans between main application and plugins. It looks like:
#Override
protected SpringBootstrap createSpringBootstrap() {
return new SharedDataSourceSpringBootstrap(this, MdSimplePluginStarter.class)
.addSharedBeanName("objectMapper")
.addSharedBeanName("cacheService");
}

Spring Test: better use XML configuration over annotations?

I'm learning Spring and looking at using Spring Test for my web app (JQuery/CXF/Hibernate). I have been using annotations to wire up my beans and noticed that this sometimes got into the way of polymorphism. For example I have a GenericDAO extended by all DAOs. It is also a concrete class used by simple services, so when I wired it for one of those services, ALL other DAOs became candidates for runtime wiring (because of polymorphism). I could solve that by wiring explicitly by type: #Resource(type= GenericDaoImpl.class), but this goes against the best practice of coding to interfaces ..
Now I want to create unit tests using a MockGenericDaoImpl, and integration tests using GenericDaoImpl. How will I override the annotations? I'm guessing the best approach is to stick to XML-based wiring, so that I can have several versions of beans.xml, one for prod, one for unit tests, one for integration tests, and possibly split them into parallel sub-files, as needed. Isn't this approach more flexible than depending on annotations that either scan to guess the appropriate candidate, or constrain polymorphism?
Can someone give me broad directions on how to organize my test configuration setup? Thank you!
How about using #Configuration class? If you're not familiar with this method - you can declare a class that replaces the XML context file and looks something like this:
#Configuration
#ComponentScan({ "com.project.dao"})
public class TestConfiguration {
#Bean
public GenericDao getGenericDao() {
return new MockGenericDaoImpl();
}
}
In the #ComponentScan annotation just put the relevant packages to scan. This way you're very flexible with the beans you're creating and the way to create them. You can injects mock to the beans whatever way you'd like.
Also you can create several test configurations, each configuration for a different purpose. In order to load the context you need to put this annotation on your test class:
#ContextConfiguration(classes={TestConfiguration .class})
Using XML configuration files prevent you from depending on Spring dependencies. You can replace it with another DI framework(maybe Guice, but this is not realistic for big projects I know). Using XML configuration files enables you to code cleanly.
I hate XML but I hate existence of not-business-logic-specific things in my code more.
I see you know how to overcome the test issues using XML configuration files. I will try to show how to overcome duplication of implementations(one real one mock implementation) problems using annotations.
You can define your beans via annotations. You can select implementation using aliases:
project.dev.properties:
my.project.dao.xDao=xDaoJpaBean
project.test.properties:
my.project.dao.xDao=xDaoMockBean
<alias name="${my.project.dao.xDao}" alias="xDao"/>
#Autowired
#Qualifier("xDao")
protected XDao xDao;
So you can select your implementation just using your properties file. If you want to use Annotations purely you can do this as well:
#Autowired
#Qualifier("${my.project.dao.xDao}")
protected XDao xDao;
Your build environment will specify which properties file to load, in return your bean will be assigned.

How to get Spring Context

I have a third party library that starting up my aplication, load spring context and save it in private static filed without any acessors.
I need to get this context to my application. Does spring provides some callbacks like afterContextLoaded methods or any other ways how to get it?
Reflection is not a solution for me!
Thanks.
you have several ways to archive that:
Use ApplicationListerner and ApplicatinEvent
Use ApplicationContextAware
Both of them can be found at http://static.springsource.org/spring/docs/3.0.0.M4/reference/html/ch03s13.html
(sorry for the link is not to the latest version)
Just implement ApplicationContextAware in a Spring bean.
If you want to access the AppContext on startup, then also implement InitializingBean and put your code in afterPropertiesSet() - the ApplicationContext instance will be populated and ready for use at that time.

Implementing DAO with Spring

I'm thinking of implementing Objectify DAO with dependency injection, such that I can maintain my code to access the same "Dao" while the implementation may change from Objectify to Hibernate-MySQL or MongoDb in the future without me worrying on changing any code in the UI or client side.
UserDao is based on the example here:
http://turbomanage.wordpress.com/2010/01/28/simplify-with-objectify/
UserObjectifyDaoImpl implements Dao<User> {
private UserDao dao = null;
public void put(User entity) {
if (dao == null) {
dao = new UserDao();
}
dao.put(entity);
}
// other put and set methods
}
Such that, I have the context.xml:
<bean id="userDao" class="com.example.server.daoimpl.UserObjectifyDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
And if I need to change the implementation, I just need to change this bean from UserObjectifyDaoImpl to something like:
UserHibernateDaoImpl or UserMongoDBDaoImpl or whatever implementation saving to whatever database.
And still have my code in the UI / Client intact, like:
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
Dao dao = (Dao) ctx.getBean("userDao");
dao.put(something);
One reason I need to do this right now, I need to develop using app engine (via objectify), however in the future I may need to change some data access objects to hibernate and some to mongodb (so its a mix).
I haven't tested this code, will this strategy work?
Yes, this will work. In fact this is one of the major reasons why DI and coding to an interface was invented. Just make sure that all DAO implementations follow the same contract (DAOs very often introduce leaky abstractions).
Also you have several other options to achieve the same goal:
Several #Service annotated classes with one marked as #Primary (if you are using autowiring)
Spring profiles and selective activation of beans
BTW if you are considering switching to a different DAO implementation, have a look at CrudRepository from Spring Data. Spring Data project provides several modules that implement this interface for MongoDB, Neo4J, JPA, etc.
For the time being it seems like several Spring Data modules do not play together nicely (see: DATAJPA-146), so if you choose to implement CrudRepository make sure this issue is fixed or you can work it around. Thanks to #iddqd for pointing that out.
You can changes context config to selected Dao implementation if you only need one implementation in application but if you need more than one implementation in your application(mixing mode), you need design Factory Layer. You trying design a layer with name Factory and with its APIs and implementations and it decide witch Dao(Hibernate, MongoDB, JP or etc) in any time must select.

Categories