Would it be technically a good and acceptable practice to inject required dependencies using an Interceptor type. For example:
public #interface Inject {
public Class thisType();
}
public class InjectionInterceptor implements HandlerInterceptor {
#Override
public bool preHandle(HttpServletRequest hsr, HttpServletResponse hsr1, Object o) {
HandlerMethod handlerMethod = (HandlerMethod) o;
Class type = handlerMethod.getBeanType();
Annotation[] annotations = type.getAnnotationsByType(Inject.class);
for(Annotation annotation: annotations){
Inject inject = (inject) annotation;
for(Field field :type.getDeclaredFields()){
if(field.getType().equals(inject.thisType())){
field.setAccessible(true);
field.set(handlerMethod.getBean(), Services.find(inject.thisType()));
}
}
....
return true;
}
...
}
A bean can have 4 scopes.
Singleton
Only one shared instance of the bean will be managed, and all requests for beans with an id or ids matching that bean definition will result in that one specific bean instance being returned by the Spring container.
It is default scope of a bean.
Prototype
New instance is returned by the container when bean with the specified id is requested.
Ex: If you have a bean with id as "employee" in your spring container, then everytime you do a
Employee emp = context.getBean("employee");
A new instance will be returned.
request, session, and global session are for use only in web-based applications
Request
A new instance is created for every single HTTP request.
Ex : Login needs different instance everytime.
Session
A new instance will be created of the bean using the bean definition for the lifetime of a single HTTP Session.
global
The global session scope is similar to the standard HTTP Session scope and really only makes sense in the context of portlet-based web applications
You can specify the scope of a bean in two ways
Using XML:
<bean id="employee" class="com.company.Employee" scope="singleton"/>
Using annotation.
mark the class with #Scope("prototype")
you can read more about scopes here
sample code for reference is available here
Related
I'm trying to instantiate a component inside a method, to be more precise inside a rest method. I need a new instance of the component every time the rest method is invoked
#Validated
#RestController
#RequestMapping("test")
public class Test {
#GetMapping
public String test() {
// Spring equivalent of
// TestComponent component = new TestComponent();
return component.uuid();
}
}
My component is defined like this
#Scope
#Component
#Transactional
public class TestComponent {
private EntityManager entityManager;
private UUID randomUUID;
#Autowired
public TestComponent(EntityManager entityManager) {
this.entityManager = entityManager;
this.randomUUID = UUID.randomUUID();
}
public String uuid() {
// entityManager transactional stuff
return randomUUID.toString();
}
}
I tried to use a factory method but the instance was not transactional, I tried to use ApplicationContext.getBean but the instance was a singleton. How can I instantiate my component dynamically whenever I need it?
I'm using Spring 3.0.0-RC1
You can use different scopes to define the life cycle and visibility of that bean in the context. The default scope is Singleton, which means only one instance is created.
In your particular case, I think that you should choose between:
Prototype - creates a new instance every time a request for that specific bean is made. It can be defined with #Scope("prototype") annotation.
Request - each HTTP request has its own instance, only valid in the context of a web-aware Spring ApplicationContext. It can be defined with #RequestScope annotation.
To find out more details about all supported scopes, check the documentation.
If I have a bean definition with some configuration within it and I use autowire to get an instance of the same class, is it the instance of the bean definition I get returned or a new instance of the class without any configurations?
class Name {
private fName;
private lName;
constructor(string fName, string lName) {
this.fName = fName;
this.lName = lName;
}
}
#Bean
public Name getName() {
Name test = new Name(thisIsMyFirstName, thisIsMyLastName);
}
--Separate File--
#Autowired
private Name testName;
Is testName here a copy of the #Bean getName() (has thisIsMyFirstName and thisIsMyLastName set) or is it a new instance of the class Name without a first name of thisIsMyFirstName and last name of thisIsMyLastName?
By default, yes, beans are singletons.
But, the Spring framework defines a number of different scopes.
singleton
Scopes a single bean definition to a single object instance per Spring IoC container.
prototype
Scopes a single bean definition to any number of object instances.
request
Scopes a single bean definition to the lifecycle of a single HTTP request; that is each and every HTTP request will have its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
session
Scopes a single bean definition to the lifecycle of a HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
global session
Scopes a single bean definition to the lifecycle of a global HTTP Session. Typically only valid when used in a portlet context. Only valid in the context of a web-aware Spring ApplicationContext.
The scope of a bean can be change using the #Scope annotation.
#Bean
#Scope("singleton") // <- singleton is the default. If no #Scope annotation is present, this is what is used.
public BeanA sharedBean() {
// This will only be called once, all subsequent calls will return from the cached reference in the ApplicationContext
return new BeanA();
}
#Bean
#Scope("prototype")
public BeanB privateBean() {
// This will be called every time the bean is injected and a new instance returned.
return new BeanB();
}
This is just another syntax
#Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
Is this possible to define a Spring bean in applicationContext.xml that takes an instance of HttpRequest as a constructor argument?
The bean I'm trying to create is an instance of org.keycloak.adapters.springsecurity.facade.WrappedHttpServletRequest. The reason behind this is that I want to use Spring AOP to intercept a method that's invoked from that class. Is this possible?
That's the constructor code:
public WrappedHttpServletRequest(HttpServletRequest request) {
Assert.notNull(request, "HttpServletRequest required");
this.request = request;
}
Question 1) From my understanding spring creates singletons objects, So when I have a controller like below with a autowired service, will that affect threadsafety.
Question 2) If I declare a int type variable at class level and use it in controller or service, will it affect thread safety?
#Controller
public class LoginController {
#Autowired
public DaoService daoservice;
#RequestMapping("/")
public String getBookInfo() {
Book book = daoservice.getBookbyId(1L);
System.out.println(book.getTitle());
return "welcome";
}
}
#Service
public class DaoService {
#Autowired
public BookRepository BookRepo;
public Book getBookbyId(Long Id) {
Book book = BookRepo.findOne(Id);
return book;
}
}
Q.1 : Are Spring Beans Thread Safe?
Answer: No.
Spring don't give you thread safety for their bean. Spring provide different type of bean scope like (Prototype,Singleton etc). If Prototype then a new bean create each time it invoke where a singleton bean created for one time and shared in application context.
If you are thinking for HTTP request, then 2 or more request can come.Hence new instance of a bean is created in each request scope. So you can think they are thread safe in context of HTTP request but it's not truly thread safe by spring itself.Because several thread can share the bean within the same HTTP request context.
Q.2 : Are Class variable Thread Safe?
Answer: No
Quoted from here
All private member variables are shared. They might be final, but that only means that the references can't be changed. Any mutable state must be synchronized.
The context is the following :
An client application uses a stateless session bean in order to login on an EJB server application. If the login is successful, the client should get a stateful session bean in order to perform some transactions on his personal data. However, I would want that the login method returns a new instance of this stateful session bean such that a client should not be able to manually call this session bean and perform transactions without being authenticated. Is it possible ?
In my stateless bean I have the following code :
#Resource
private SessionContext context;
...
public StatefulBeanRemote login(username, password) {
if (ok) {
StatefulBeanRemote bean = (StatefulBeanRemote) context.lookup("StatefulBeanRemote");
return bean;
}
The lookup always fail. I don't know what I am doing wrong...
The lookup you're performing is the same as:
new InitialContext().lookup("java:comp/env/StatefulBeanRemote");
Have you defined an EJB reference to StatefulBeanRemote? Perhaps that is all you need:
#EJB(name="StatefulBeanRemote", beanInterface=StatefulBeanRemote.class)
public class MyClass {
#Resource
private SessionContext context;
...
}