Spring beans used in two different scopes - java

We have a Web Application exposing both Web Resources (REST) and JMS MessageListener. Spring is the framework used to define and inject beans.
We defined beans in the scope "request" to store information usable for Web Resources. We would like to use those beans also in the JMS MessageListener, but the "request" scope does not exist and cause an exception.
One solution of this problem is to use a custom scope of type "thread" as implemented with the "SimpleThreadScope" of Spring. But the destruction of the beans is not implemented in this class. I know there is a way to implement this with the "Spring custom scope thread by example", but I prefer letting the Application Server manage the thread pool.
Do you have any other idea/suggestion about this issue?
Important aspect: the beans created in the scope are used as by resources as well as by JMS Message Listener.
Let's take an example.
Imagine we have the following classes:
Class BeanInScope1
Class WebResource1
Class Service1
Class MessageListener1
The "Service1" uses the "BeanInScope1", and the "Service1" can be called either by "WebResource1" or by "MessageListener1", meaning that the "BeanInScope1" msut be created in the same way by "WebResource1" and "MessageListener1".
Hope this example shall help...

Related

Spring hierarchy visibility best practice

I am trying to understand how to best make use of spring application context hierarchies. Assuming I have an Application where I have #Controller beans, #Service beans, and #Repository beans, representing a front-end, business and persistence layer, it would seem nice if the layers had contexts in which only beans are visible which are relevant to the context. It would also be nice if I did not need special code for creating beans, just using #Autowired should be enough.
I can create a context for my repositories, let's say repoContext, in which there exist only the repository beans. The service layers needs access to those, but not vice versa, so I'd might create another context serviceContext which has repoContext as parent. Now the front-end layer needs the services, so I might create a controllerContext with serviceContext as parent. But doing so, the controllerContext would also be able to deliver repository beans to the front-end layer, which is the opposite of what I wanted.
So it seems to me that to properly separate bean dependencies in separate contexts, the parent-child relationship is not very useful to provide dependencies to a context.
Is there any better way? Could there be a front-end and a backend context sharing configuration of the service beans, but with the backend context being resposible to insatntiate service beans first (because only this context has repositories)? Or would that approach lead to the frontend context trying to instantiate own service beans?

How do CDI beans behave when accessed by a JAX-WS web service?

I want to expose some functionality of my existing JEE7 web app using a SOAP based #WebService. Can/should this service inject my app's CDI beans? How do #RequestScoped, #SessionScoped, and #ApplicationScoped CDI beans behave, given that there's no HttpServletRequest to identify the current session or request? ie. How do they get looked up?
My observations:
#ApplicationScoped seems to work as expected
#SessionScoped seems to behave like request scope in that a new bean is created each time the web service is called, but it is subsequently accessible from other beans up until the service completes
#RequestScoped beans don't seem to be looked up property - eg. if my webservice injects two #RequestScoped beans, then one of those injects the other one, a new instance is created, rather than the first one being injected
My idea was to use the #Dependent annotation to make my session beans behave like request beans when injected into my #WebService, but this isn't working due to the request scoped behaviour noted above. I could just use my #SessionSoped beans as they are, but I'm concerned about the memory overhead since a new bean would be created for every web service request, and then persist for some 30 minutes or so, rather than being destroyed once the service has completed.
Any clarification or ideas would be appreciated!

CDI choosing correct scope for bean

Coming from plain old DI of Spring I can't figure out how to choose scopes properly while writing with CDI.
In Spring all my services have singleton scope by default, which I suppose maps to application scope in CDI (or even #Singleton). I know for e.g. logged in user information I need to use Session scope and for e.g. form params I need request scope.
Say I have a bean that hides external service API calls. It is completely stateless. Should I put it as #Singleton or simply application scoped? Or let it be created on every request (possibly bad option).
Is this correct to inject everything everywhere? In Spring I create my data objects by new. Should I do the same in CDI or simply #Inject them?
Are you only using CDI? or a Java EE 6 container? If you have a stateless class that is used for service calls, then I would recommend using #Stateless, which is from the EJB spec (so you would need a Java EE 6 container) It isn't a singleton, but it doesn't get created on each request either. I believe it is more closely bound to the session, but since it is stateless, instances can be pooled and shared. If you are only dealing with CDI, I believe Singleton matches more directly to Spring's singleton, but I would recommend using ApplicationScoped because it provides a proxy which makes serialization of beans that use it easier.
#Service
#Scope("prototype")
public class CustomerService
{
......
}
Just add #Scope("prototype") annotation to your component.
Is there a reason you would need the bean to remember it's state? If you are using something like a web client, that is a better place to store state in say, session scoped managed beans (assuming jsf), or whatever equivalent for your case. On the back end server side your EJB's would be better kept as #stateless to keep overhead to a minimum and help with the 'keep it simple s..." paradigm. And in case this works, just declare #Stateless on your bean. Unless there is a reason to use a singleton, again it is better to use a stateless bean if you want to go with a Java EE container for your services.
Stateless beans are not really being recreated with every request. That is the purpose of the pool. The app server keeps a ready supply of stateless beans on hand, and if it gets busy, it will make more, and if it quiets down, it will empty some out.

bidirectional dependency between web applicaton context and service context

I have 2 spring contexts: "webapplication" context and a "core" context. The context "core" is initialized at server startup and attached to a Singleton class that holds the context. The "webapplication" context is initialized when the webapplication is started.
I want to inject bean dependencies from beans in one context to the other (bidirectional access). The webapplication beans are to be "session" scoped beans.
I'm testing this proof of concept with: webapp bean --> (that depends on) core bean --> (that depends on another) webapp bean.
At the webapplication context initialization i could inject "core" beans to the "webapplication" beans (a BeanFactory that acceses the singleton do the magic), but can't figure out how to do the inverse; because the Spring ThreadLocal that holds the WebApplicationContext is not yet initialized.
The question is. Is it what i'm trying to do possible? If the answer is "yes", how would you do that?
Thank's in advance.
EDIT:
I'd realized i'm doing something wrong. The fact is that i'm trying to inject in the service layer a dependency to a session bean, at the wrong time; that is, at the web initialization time when i have no current user session.
This looks to me like an architectural issue, not a technical (and certainly not Spring) one. Your separation between core context and web context is very good. The former handles business processes while the latter is responsible for representation, maybe some API.
The dependency from web (representation, access) to core is understandable and required - after all you are building an interface over business routines. This is how spring-mvc works by default, creating separate child (web) application context of core context.
I can hardly imagine a use case for inverted dependency. Why is your business logic depending on web layer? What if you try to migrate your application one that to a different representation technique (desktop, mobile)? Can you justify the reason for this inverted dependency? What do you mean by session bean?
Bidirectional dependencies, as well as static singletons holding a class-loader wide reference to application context should indicate that something is wrong with the design.

should a Service layer be a Spring bean?

Can or should a Service layer be a Spring bean?
If so, how should it be got from a calling application, a consumer of a service?
Because the consumer must be aware that such a bean exists, so it in any case must use Spring
to make use of Service methods.
Of course. The service layer is the part of your application that is visible to other users (e.g. a Web layer) so it needs to be configured and setup somewhere. Imho a Spring configuration is the best place to put this configuration in. The Service Layer user then has to take care of instantiating that context and getting the Service Objects he needs.
An alternative - if it needs to run standalone - would be for your service class(es) implementing the Service Layer interface(s) to instantiate the Spring application context themselves.
By making your consumers also spring beans, and inject the service bean with dependency injection.
Yes, It is always nice to configure service beans as spring beans. In the web layer you need to take care of instantiating the needed service objects. Another option is to make the web layer classes also as spring beans and inject the necessary service layer spring beans. From the testing point of view also, this type of design is very helpful when we use Spring testing framework.

Categories

Resources