My question is :
let's assume that i have a spring bean : a DAO one (it's a singleton of course)
So, when we have lot of users who want to use this bean at the same time : what happens?
or,
for every user, spring instantiate a DAO bean for him?
==> we have a singleton by application Context : did spring create a context for every user?
(it's a singleton of course)
Then it's a singleton. The ApplicationContext will only create one instance and pass that same instance around wherever it's requested.
for every user, spring [instantiate] a DAO bean for him?
No, it will retrieve and give them the same DAO instance.
==> we have a singleton by application Context : did spring create a context for every user?
I'm not exactly sure what you mean for every user. A Java application has no knowledge of users. If you mean in the context of a multithreaded application, it's still irrelevant. The injected DAO bean will still be that single instance.
As stated in the comments, it's your responsibility to handle the state of your DAO, if it's mutable, handle concurrent access. Handle transactions (possibly with #Transactional) with the datasource.
You dont use DAOs as Spring beans. Spring beans (singleton scope) are more like a service.
Lets say you have a Pizza Dao, and a PizzaService, your Service is a spring bean, while pizza isnt.
class Pizza {
Set ingredients = ... ;
public Pizza(Set s) {
...
}
private addIngredient(Object o ) {
set.add...
}
}
#Service
class PizzaService {
private Pizza createPizza(..){
Pizza p = new Pizza();
....
return pizza;
}
private void persistPizza(Pizza pizza){
..save to db..
}
}
Test your service:
class JunitFoo{
#Autowired private PizzaService service;
#Test
someMethod(){
Pizza p = service.createPizza();
p.addIngredient(cheese)
service.persistPizza(p);
}
}
You can also implement Runnable in JunitFoo and launch someMethod a lot of time with differents threads (your User), every user will get its own Pizza. But all users use the same pizzaService.
Due to this reason singleton is default scope of a spring bean. You can also create a Pizza by fetching it from your application context, but in this case, you would need prototype otherwise all users share the same pizza
<bean id="pizza" class="foo.Pizza" scope="prototype" >
<default set of pizza stuff>
</bean>
If you do it that way, your PizzaService could look like this:
#Service
class PizzaService {
#Autowired private ApplicationContext context;
private Pizza createPizza(..){
return (Pizza) context.getBean("pizza");
}
private void persistPizza(Pizza pizza){
..save to db..
}
}
This topic is way to big to cover it in a single post, i hope i could help and improve your understanding. Please also check the spring documantation about bean scopes.
Related
I have a java web application developed on Spring framework which uses mybatis. I see that the datasource is defined in beans.xml. Now I want to add a secondary data source too as a backup. For e.g, if the application is not able to connect to the DB and gets some error, or if the server is down, then it should be able to connect to a different datasource. Is there a configuration in Spring to do this or we will have to manually code this in the application?
I have seen primary and secondary notations in Spring boot but nothing in Spring. I could achieve these in my code where the connection is created/retrieved, by connecting to the secondary datasource if the connection to the primary datasource fails/timed out. But wanted to know if this can be achieved by making changes just in Spring configuration.
Let me clarify things one-by-one-
Spring Boot has a #Primary annotation but there is no #Secondary annotation.
The purpose of the #Primary annotation is not what you have described. Spring does not automatically switch data sources in any way. #Primary merely tells the spring which data source to use in case we don't specify one in any transaction. For more detail on this- https://www.baeldung.com/spring-data-jpa-multiple-databases
Now, how do we actually switch datasources when one goes down-
Most people don't manage this kind of High-availability in code. People usually prefer to 2 master database instances in an active-passive mode which are kept in sync. For auto-failovers, something like keepalived can be used. This is also a high subjective and contentious topic and there are a lot of things to consider here like can we afford replication lag, are there slaves running for each master(because then we have to switch slaves too as old master's slaves would now become out of sync, etc. etc.) If you have databases spread across regions, this becomes even more difficult(read awesome) and requires yet more engineering, planning, and design.
Now since, the question specifically mentions using application code for this. There is one thing you can do. I don't advice to use it in production though. EVER. You can create an ASPECTJ advice around your all primary transactional methods using your own custom annotation. Lets call this annotation #SmartTransactional for our demo.
Sample Code. Did not test it though-
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface SmartTransactional {}
public class SomeServiceImpl implements SomeService {
#SmartTransactional
#Transactional("primaryTransactionManager")
public boolean someMethod(){
//call a common method here for code reusability or create an abstract class
}
}
public class SomeServiceSecondaryTransactionImpl implements SomeService {
#Transactional("secondaryTransactionManager")
public boolean usingTransactionManager2() {
//call a common method here for code reusability or create an abstract class
}
}
#Component
#Aspect
public class SmartTransactionalAspect {
#Autowired
private ApplicationContext context;
#Pointcut("#annotation(...SmartTransactional)")
public void smartTransactionalAnnotationPointcut() {
}
#Around("smartTransactionalAnnotationPointcut()")
public Object methodsAnnotatedWithSmartTransactional(final ProceedingJoinPoint joinPoint) throws Throwable {
Method method = getMethodFromTarget(joinPoint);
Object result = joinPoint.proceed();
boolean failure = Boolean.TRUE;// check if result is failure
if(failure) {
String secondaryTransactionManagebeanName = ""; // get class name from joinPoint and append 'SecondaryTransactionImpl' instead of 'Impl' in the class name
Object bean = context.getBean(secondaryTransactionManagebeanName);
result = bean.getClass().getMethod(method.getName()).invoke(bean);
}
return result;
}
}
having this generic DAO definition
#Repository
public class GenericService<T> implements IGenericService<T> {
#PersistenceContext(unitName="mgrUnit", name="mgrEMF")
#Qualifier(value = "mgrEMF")
public void setEm(EntityManager em) {
this.em = em;
util = em.getEntityManagerFactory().getPersistenceUnitUtil();
}
}
and having a large number of Entities, i want to automatiqualy instanciate DAO, Back-End Beans for basic tables like ( Region, EmployeSpeciality... )
For the bean registration and instantion it's easy but what about the DAO ?
I must precise that in my case the EntityManager depends on the service, i have a multiple Database connection.
i read this article but honnestly it looks to much complicated
http://doanduyhai.wordpress.com/2011/11/20/spring-transactional-explained/
Is there a simple way to do it ?
OK, using
AutowireCapableBeanFactory beanFactory =
FacesUtils.getWebappContext().getAutowireCapableBeanFactory();
beanFactory.autowireBean(obj);
It solve the half of the problem, the Bean EMF is correctly injected, but the bean is not registred (i must re-instanciate it every time i need), because the beanFactory doesnt contains the Bean Definition, so how to add it?
NB: i know that puting the object in the application MAP can keep the DAO accessible but its not a serious solution
FacesContext.getCurrentInstance().getExternalContext().
getApplicationMap().put( serviceName, service);
IGenericService service = (IGenericService) ContextManager.findBean( serviceName );
if (service==null && !FacesUtils.getWebappContext().getBeanFactory().
containsBeanDefinition(serviceName)){
service = new ErpGenericService(clazz);
AutowireCapableBeanFactory beanFactory = FacesUtils.getWebappContext().
getAutowireCapableBeanFactory();
beanFactory.autowireBean(service);
//Applying transactional proxies
service = (IGenericService) beanFactory.applyBeanPostProcessorsAfterInitialization(service, serviceName);
FacesUtils.getWebappContext().getBeanFactory().
registerSingleton(serviceName, service);
}
I was wondering which one of the two solutions hereunder is the best practice?
Problem : I have a stateless session bean VehicleBean, I implemented a method with business logic and persistence of a Car with its wheels , their tires, etc.
#Stateless
class VehicleBean{
#PersistenceContext
private EntityManager em;
#EJB
Inspector inspectorBean;
#EJB
DocumentBean documentBean;
public void persistCar(){
Car car = new Car();
car.setMake("Ford");
em.persist(car);
documentBean.persistDocument(new Document(car));
for (int i = 0; i < 4; i++){
createWheel(car);
}
private void createWheel(Car car){
// some business logic
inspectorBean.inspect();
Wheel wheel = new Wheel();
wheel.setCar(car);
em.persist(wheel);
...
}
...
}
I have different private methods that are called after each other (1) create car, 2) create wheels, etc) and I would like to regroup all these methods in one helper class.
Solutions:
1) Make use of a helper class CarBuilder which contains all the private methods from my VehicleBean. As I can't use ejb injection, I want to pass it by reference to the constructor as following :
public void persistCar(){
new CarBuilder(this, document, inspectorBean);
}
class CarBuilder{
private VehiculeBean vehiculeBean;
...
CarBuilder(VehiculeBean,....){
this.vehiculeBean = vehiculeBean;
}
}
2) create CarBuilder as a stateless session bean and inject the bean in the VehiculeBean.
Do you see any advantage using the 2)? So having a lot of different beans like CarBuilder, MotorcyleBuilder, etc managed by the container.
Passing references to container managed objects in constructors will decrease readability of the code (IMO). Code becomes a lot clearer if you create container managed resources with dependency injection.
Let the helper classes work with the entities instead and create a new EJB when you want to break out bussiness logic in another class.
I have code which looks like the following:
MyContext context = new MyContext();
context.start();
MyEntity entity = context.getEntity();
I want to inject the MyEntity instance into various classes.
But I don't know how to setup my Spring configuration, where I first create an object, then call a method on it and then finally call another method which returns the entity I want to inject.
EDIT 2 - removed the Strings altogether
The most common type of dependencies injected using Spring don't depend on the user input for their construction. This includes data access objects, services etc.,
You are talking about injecting domain objects whose construction depends on the user input either directly or indirectly.
Spring provides #Configurable annotation to inject such domain objects that are created using new operator. You can search for "#Configurable Domain Driven Design" on the internet to get examples of how this can be implemented. I myself used it in one my applications and wrote a simple post here that might help you get started.
Edit:
To create a bean of type MyEntity as per the specification in your updated question, you would need to
define a bean of type MyContext
Create a MyEntityFactory class that would depend on the MyContext bean.
The factory method would take the MyContext bean as argument, calls context.start() on it and returns an instance of MyEntity.
You would define the MyEntity bean using this factory class.
The MyEntityFactory class would be as follows:
public class MyEntityFactory
{
public static MyEntity getMyEntity(MyContext context)
{
context.start();
return context.getEntity();
}
}
The spring bean configuration will be as follows:
<bean id="myContext" class="FQCN.Of.MyContext" />
<bean id="myEntity" class="FQCN.Of.MyEntityFactory" factory-method="getMyEntity">
<constructor-arg ref="myContext" />
</bean>
Since MyEntity is a singleton bean, the factory method will be called only once, btw.
More on creating beans using factory methods here.
I would like my other classes to interact with my domain's interfaces rather than implementation, and i would like to avoid hardcoding the implementation in the code, such as this example :
public void addToMyList(String s, int i) {
DomainModel model = new DefaultDomainModelImpl(); // it's hardcoding the implementation here
model.setName(s).setAge(i);
myList.add(model);
}
If i use spring container, with the prototype scope, i can use something like :
// <bean id="myDomainBean" scope="prototype" class="my.package.domain.MyDomainImpl" />
DomainModel myDomainModel = springContext.getBean("myDomainBean");
But i would like to avoid accessing springContext explicitly in my code.
I wonder what's the clean way to do this ?
Im currently thinking of creating a factory implementation for each domain implementation, and autowire the factory to create the beans, but that means different implementations of my domain will have different implementations of the factory also.
Please share your opinions, thank you !
Im currently thinking of creating a factory implementation for each domain implementation, and autowire the factory to create the beans, but that means different implementations of my domain will have different implementations of the factory also.
That is not 100% correct. You can have a factory that take the Interface (class) of the Domain objects that needs to be create. You can inject that factory in you class.
So you will get all the requriements you asked for:
no hard coded new
the domain object code has no dependence to spring
you only have one factory class and one factory method.
example
#Inject
MyStrangeSpringHiddingFactory myStrangeSpringHiddingFactory;
DomainModel myDomainModel = this.myStrangeSpringHiddingFactory.
createInstanceOf(DomainModel.class);
class MyStrangeSpringHiddingFactory implements MyStrangeSpringHiddingFactory {
#Inject
ApplicationContext springContext:
public <T> createInstanceOf(Class<T> clazz) {
return springContext.getBean(clazz);
}
}
This are only my thoughts, because I do not know your use case: Do you really need such in abstraction? Do you really have a domain model where a domain class have several subclasses that need a factory.