I have a #SessionScoped? DAO that's being injected into a Stripes framework Interceptor constructor that seems to be found from the interceptor (on subsequent calls) but is not being injected into a service in the same request (and session). Why isn't the same instance (initialized in the interceptor) being reused in the service (which is in a different package in the same project)?
Making the DAO a #Singleton does the trick, but is unacceptable as the DAO stores information that must remain consistent throughout a user's session on an application that has multiple users who would be sharing the same DAO instance.
If the Interceptor is not a session-scoped object, then you'll need to inject Provider<YourDaoType> into the Interceptor. This is the common pattern to use when an object with a long life depends on another object with a shorter life.
ok, I've figured it out. I changed the #SessionScoped to a bind(DAO.class).in(ServletScopes.SESSION) statement with which the injection works. As far as I understand, these should be equivalent, but in my case they're producing different results.
One aspect that was troubling me along the way was that Stripes built the interceptor that injected the DAO on startup causing errors as this happened outside the scope of a session (which the DAO is #SessionScoped. ActionBeanContext context information is needed to initialize the DAO session context which I set in an AbstractActionBean setContext method that is called during the construction of the action bean.
Thanks for your interest and help.
Related
Im really new to java, jsf, jsp, and I need to learn how it works quickly. So the website Im using to practise has some terms etc that I dont know what they mean and Im hoping somebody can explain what they mean and how/what they are used for:)
Requestscoped
Applicationscoped
Sessionscoped
EntityManager
and could someone walk me through what these lines do?
#RequestScoped
public class Dao {
#DataRepository
#Inject
private EntityManager entityManager;
First of all, in Java (5 and higher), "things" starting with a # (e.g. #Deprecated) are called annotations.
Annotations provide data about a
program that is not part of the
program itself. They have no direct
effect on the operation of the code
they annotate.
Your JavaBeans needs to be configured to a scope if you want to use it in JSF (Definitions can be found here).
#RequestScoped: Objects with this scope are visible from the start of the request until the end
of the request. Request scope starts at the beginning of a request and ends when the
response has been sent to the client. If the request is forwarded, the objects are visible
in the forwarded page, because that page is still part of the same request/response
cycle. Objects with request scope can use other objects with none, request, session,
or application scope. If you have to think it in terms of servlet, the managed bean is stored in the HttpServletRequest until the end of the request (when the response is sent to the client). After that, the bean no longer exists in the request.
#SessionScoped: An object with session scope is visible for any request/response cycle that
belongs to a session. Objects with this scope have their state persisted between
requests and last until the object or the session is invalidated. Objects with session
scope can use other objects with none, session, or application scope. Basically, these objects are stored in a HttpSession (refer to Servlets again). Each session has a session ID (known as JSESSIONID) that the bean is associated with.
ApplicationScoped: An object with application scope is visible in all request/response cycles
for all clients using the application, for as long as the application is active. In terms of Servlet, this could be, managed bean stored in a ServletConfig.
#NoneScoped: Objects with this scope are not visible in any JSF page. When used in the configuration file, they indicate managed beans that are used by other managed beans in the application. Objects with none scope can use other objects with none scope.
For EntityManager, this is associated with persistence context. It is used to create and remove persistent entity instances, to find entities by their primary key identity, and to query over all entities. For more, refer to the JPA (Java Persistence API) Specification, or Hibernate.
#Inject, means that the instance is injectable. They follow the infamous crase word of Depency Injection or Inversion of Control (IOC). What this basically mean, is that when the resource (in your case EntityManager entityManager is needed, the JEE container instantiates the resource for you (without you needed to instantiate it directly through e.g. a constructor, etc.).
I have no clue what #DataRepository means. Never seen it before.
I hope this helps you.
These terms are usually associated with a dependency injection framework like guice and not with java in particular.
http://code.google.com/p/google-guice/wiki/Scopes describes the various scopes that are built into guice.
By default, Guice returns a new instance each time it supplies a value. This behaviour is configurable via scopes. Scopes allow you to reuse instances: for the lifetime of an application (#Singleton), a session (#SessionScoped), or a request (#RequestScoped). Guice includes a servlet extension that defines scopes for web apps. Custom scopes can be written for other types of applications.
Obviously using stateless EJB beans in an entity bean smells, but please consider a scenario as follows and tell me if you know of a better solution:
I have an InvoiceTemplate Entity Bean with field NextInvoiceDate
Generating NextInvoiceDate is a complex procedure and should be performed outside of the InvoiceTemplate class
NextInvoiceDate should be updated each time InvoiceTemplate is stored to the db
For now I have logic regarding the generation of NextInvoiceDate in #PrePersist #PreUpdate methon in InvoiceTemplate entity bean. The logic is getting more and more complicated and I want to move it outside of the InvoiceTemplate entity bean. It looks to me that there should be a service to calculate NextInvoiceDate. But then is it right to invoke this service from the inside of InvoiceTemplate?
It isn't such a smell - it is a lean towards domain-driven design.
I don't know of any way to do this automatically, but you can:
in the session beans where you handle your Invoicetemplate, inject the helper bean that has the logic to calculate the next date
create a private field with a setter on the entity, and before you start using it call entity.setNextDateHelper(..)
You can also check whether AspectJ doesn't offer some EJB options so that you can inject the EJB whenever an entity of a given type (InvoiceTemplate) is created. AspectJ works like that with spring beans, I don't know whether there are such options for EJB.
Do you need anything as complicated as a service or EJB? Can you just write a static method (possibly on a utility class) to hold the logic? Normally I'm pretty biased against this sort of thing, but if all you've got is some complex logic that doesn't require any DB interaction or a lot of object collaboration, it may be the cleanest approach.
What is the responsibity of the proxy class in AOP? What is the role of that?
Dynamic proxies are used to execute additional code before/after methods of your beans. The most trivial example is transaction handling:
spring creates a proxy around your beans that need transactions
if a method is declared transactiona (e.g. annotated with #Transactional) the proxy starts a new transaction and delegates to the real method
the real method executes and returns
the proxy now commits (or rollbacks) the transaction
Thus your code becomes transaction-agnostic. And when a transactional bean is injected into another one, it is actually the proxy that gets injected (which is of the same type as your bean)
And proxies are dynamic, because spring does not know at compile time the types of all your beans, so it has to create the proxies at runtime.
A long question, please bear with me.
We are using Spring+JPA for a web application. My team is debating over injecting EntityManagerFactory in the GenericDAO (a DAO based on Generics something on the lines provided by APPFUSE, we do not use JpaDaosupport for some reason) over injecting an EntityManager. We are using "application managed persistence".
The arguments against injecting a EntityManagerFactory is that its too heavy and so is not required, the EntityManager does what we need. Also, as Spring would create a new instance of a DAO for every web request(I doubt this) there are not going to be any concurrency issues as in the same EntityManager instance is shared by two threads.
The argument for injecting EFM is that its a good practice over all its always good to have a handle to a factory.
I am not sure which is the best approach, can someone please enlighten me?
The pros and cons of injecting EntityManagerFactory vs EntityManager are all spelled out in the Spring docs here, I'm not sure if I can improve on that.
Saying that, there are some points in your question that should be cleared up.
...Spring would create a new instance of
a DAO for every web request...
This is not correct. If your DAO is a Spring bean, then it's a singleton, unless you configure it otherwise via the scope attribute in the bean definition. Instantiating a DAO for every request would be crazy.
The argument for injecting EMF is that
its a good practice over all its
always good to have a handle to a
factory.
This argument doesn't really hold water. General good practice says that an object should be injected with the minimum collaborators it needs to do its job.
I am putting down what I have finally gathered. From the section "Implementing DAOs based on plain JPA" in the Spring Reference:
Although EntityManagerFactory instances are thread-safe, EntityManager
instances are not. The injected JPA EntityManager behaves like an
EntityManager fetched from an application server's JNDI environment,
as defined by the JPA specification. It delegates all calls to the
current transactional EntityManager, if any; otherwise, it falls back
to a newly created EntityManager per operation, in effect making its
usage thread-safe.
This means as per JPA specifications EntityManager instances are not thread safe, but if Spring handles them, they are made thread safe.
If you are using Spring, it is better to inject EntityManagers instead of EntityManagerFactory.
I think this has already been well covered, but just to reinforce a few points.
The DAO, if injected by Spring, is a
singleton by default. You have to
explicitly set the scope to prototype
to create a new instance every time.
The entity manger injected by
#PersistenceContext is thread safe.
That being said, I did have some issues on with a singleton DAO in my multi-threaded application. I ended up making the DAO a instanced bean and that solved the problem. So while the documentation may say one thing, you probably want to test your application thoroughly.
Follow-up:
I think part of my problem is I am using
#PersistenceContext(unitName = "unit",
type = PersistenceContextType.EXTENDED)
If you use PersistenceContextType.EXTENDED, keep in mind you have to, if I understand correctly, manually close the transaction. See this thread for more information.
Another Follow-up:
Using an instanced DAO is an extremely bad idea. Each instance of the DAO will have its own persistence cache and changes to one cache will not be recognized by other DAO beans. Sorry for the bad advice.
I found that setting the #Repository Spring annotation on our DAOs and having EntityManager managed by Spring and injected by #PersistenceContext annotation is the most convenient way to get everything working fluently. You benefit from the thread safety of the shared EntityManager and exception translation. By default, the shared EntityManager will manage transactions if you combine several DAOs from a manager for instance. In the end you'll find that your DAOs will become anemic.
First off, I think I'm trying to use Spring incorrectly, but confirmation would be appreciated.
I am trying to reset a single bean in mid-application. My initial configuration works just fine.
My scenario
1 Insurance Claim bean (session
scope)
1 Claim details bean which is a
multiactionController
(getClaim&setClaim enabled, prototype
scope)
1 Claimant details bean which is a
multiactionController
(getClaim&setClaim enabled, prototype
scope)
1 Submit claim bean which is a
multiactionController
(getClaim&setClaim enabled, prototype
scope).
My application is more complex than this, but for the sake of providing a clear example I wont describe the whole thing.
The first two controllers are used to set various properties of the claim, validate etc.
The third writes a claim to the database. THEN I want it to reset the bean. However I can't just say claim=new Claim() in SubmitClaimController.OnSubmit() as the ApplicationContext keeps its reference to the old Claim.
I could just create a method Claim.clear(), but that feels like the wrong approach. However, I can't see anything like ApplicationContext.destroyBean(beanname) or ApplicationContext.createBean().
I do not want to refresh the entire ApplicationContext as I will have other beans I want to keep alive throughout the session.
Thanks in advance.
I don't think the Claim object should be Spring-managed. It's really not injected; sounds like it should be bound from the request sent into the controller and passed to the service for processing. If you put a Claim into session scope, you need to invalidate the session when the transaction is done or if the session times out.
By the way, I see you mention three controllers, but no service. You should have a service layer, and controllers should not deal with DAOs or persistence.
You can change the scope of a bean. Default is singleton which is sometimes not appropriate in web contexts. You can change it to be session scoped by adding for example
the attribute scope="session"
and the child <aop:scoped-proxy proxy-target-class="false"/>
to the bean definition.
I am working with 3.0M4, btw, but I would expect it to be in earlier versions, as well, as it's a very important functionality. Have a look at:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/ch03s05.html
Cheers!