Unrecognized Spring cache annotations when self-invoking a method from within the same bean - spring-cache

Dear Spring Cache project community,
currently I'm implementing an Apache CXF-based Spring (version 4.1.5) web service endpoint using the contract 1st approach. Here, I observe when annotating a public method within my web service class, the Spring cache annotations "#Cachable" are ignored each time I call this method in a self-invoked way within the same bean. This could be proven when taking a look on the cache repository (via JMX) of the underlying cache provider (here: EhCache). There, no filling of the cache takes place.
After taking a look on the current Spring documentation below
Enable caching annotations and
The dispatcher servlet I assume it might be due to the fact that:
<cache:annotation-driven/> only looks for #Cacheable/#CachePut/#CacheEvict/#Caching on beans in the same application context it is defined in. This means that, if you put in a WebApplicationContext for a DispatcherServlet, it only checks for beans in your controllers, and not your services. See Section 17.2, “The DispatcherServlet” for more information.
Currently, an Apache CXF "CXFServlet" registered within the "web.xml" deployment descriptor is starting a Spring WebApplicationContext using the "cxf-servlet.xml" Spring application context file by default. There, the <cache:annotation-driven/> is located.
Or is it maybe due to the fact that I'm calling the #Cacheable annotated method from within the same Spring bean so that the generated Spring proxy is bypassed? Details can be found in the "Proxy mechanisms" chapter (9.6) of the Spring documentation as well.
But I do not know how to change the behaviour so that my method results are being cached. Do you have any ideas? Or are my assumptions I posted above incorrect?

Dear Spring community,
I found the important comment within the Spring documentation that approves my assumption:
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual caching at runtime even if the invoked method is marked with #Cacheable - considering using the aspectj mode in this case. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. #PostConstruct.
In consequence this means refactoring the code when relying on Spring AOP and its proxy mode technique or switching the mode from "proxy" to "aspectj" <cache:annotation-driven mode="aspectj"/>. This allows using self-invoking methods within the same class as AOP does static respectively dynamic weaving and so manipulates the byte code directly.

Related

What is the difference between Groovy Micronaut's #Client injected RxHttpClient vs RxHttpClient.create?

I'm creating a Micronaut HTTP Client using the #Client annotation in Groovy, and the compiler complains if I use anything other than a static constant. However, this limits me from being able to change the URL per environment by passing in a config value.
So I tried using RxHttpClient.create(myUrl) in my service instead, and the same request I'm making returns a 403. The RxHttpClient docs say
Create a new HttpClient. Note that this method should only be used
outside of the context of an application. Within Micronaut use Inject to > inject a client instead.
This doesn't explain why I shouldn't use the create method, and I'm left with an inability to make requests to different servers on different environments. What is the difference between the two clients I'm creating?
The #Client annotation will inject a managed client that has been dependency injected with additional instrumentation features for tracing, propagation etc. By using create Micronaut cannot dependency inject the instance so certain features of the framework won't work.
In addition with create you have to ensure you manually close the client since Micronaut cannot manage the life cycle and cleanly shutdown the client when the application shuts down.
Finally regarding using a static constant to #Client, it is not true that this limits you since the value can include placeholders. For example:
#Client("${my.server}")
Then in application.yml you can configure:
my:
server: http://foo.com
Or even better you can use the new HTTP services feature. See https://docs.micronaut.io/latest/guide/index.html#serviceDiscoveryManual

Thread-safety of #FlowScoped beans

I have done a small experiment with #FlowScoped beans, whose purpose, as I understand, is to make easier creating "wizard-type" web applications, gradually accumulating data over a sequence of pages, then, once all the data is ready, writing it to the persistent storage (this is just an example, nothing prevents of course to write to the persistent storage during intermediate steps). As I saw, the calls to a #FlowScoped bean are not synchronized, and thus there is in principle the possibility of corrupting the data stored in the bean (by doing a double submit, or launching by any other means two almost simultaneous HTTP requests, which invoke the methods of the bean). This unlike #ConversationScoped beans the calls to which are synchronized.
What puzzles me is that about #SessionScoped beans I have found several links which speak about the need to synchronize the access to a #SessionScoped bean (or recommending not to use them at all, apart from user data which changes rarely), but I have not found anything like that about #FlowScoped beans.
What is considered then to be a "best practice" for using #FlowScoped beans? Am I missing something?
EDIT
#FlowScoped seems, at least to me, to be motivated in part by Spring WebFlow, with which I have some experience, and which, as I know, offers integration with JSF 2 (not all JSF 2.2 features seem to be implemented, but it seems that PrimeFaces is usable, for example). I know that Spring WebFlow + JSF is actually used in "real world" applications, and the issue of thread safety of flow scoped objects is handled there elegantly together with double submit issues (flow execution id must be supplied with each HTTP request, and it expires and a new one is returned after a HTTP request which invokes a Spring WebFlow "action" method: therefore one cannot invoke concurrently more than one "action" method for the same user and flow id).
So I want to understand, what is the best practice in the case of JSF 2.2 if I wish to use the #FlowScoped beans to construct an application "flow" (without using Spring WebFlow). Do I really need to synchronize the access to #FlowScoped beans myself, or there is some standard way to deal with such issues?

Spring integration - defining base beans in configuration

Is it possible to define, within XML, a standard Spring Integration bean as an abstract bean which can be overridden. The idea of course would be to minimize configuration.
For instance, say one needs several jms:message-driven-adapter beans, all which share some common properties. How could one define an abstract bean with those properties, and then override it with concrete beans which have just the parameters which are different between each instance?
Thanks
You cannot do it with the namespace; but the JMS message-driven adapter is a relatively simple component that you can define with normal <bean/> syntax. You would need to wire together a JmsMessageDrivenEndpoint which takes an AbstractMessageListenerContainer (DefaultMessageListenerContainer) and a ChannelPublishingJmsMessageListener in its constructor.
In general, taking a look at the namespace parser for each component will tell you what <bean/>s to define.
Another technique is to define a "mini" application context defining the endpoint with property placeholders and then create a new instance of the context each time, making the main context the parent.
The general technique is explored for outbound ftp endpoints in this sample. However, it does not make its contexts children (because it's not needed there). However, the README has a link to a forum thread that explains that mechanism, when used for dynamic inbound endpoints.

Spring #Controller lifecycle

I am new to Spring MVC and would like to know how it handles requests, more specifically:
I would like to know how a Spring
#Controller's life cycle relates to
that of a Servlet?
I would also like to better
understand what are the best
practices for multi-threaded
enviornments (e.g. like in Servlets,
are class attributes visible to
multiple HTTP requests as objects are
reused from the pool)?
A controller (as any spring bean) has a scope.
At best your controllers should be of scope singleton. In that case it is very much like servlets, and:
they are created only once, during the application context startup (and destroyed when the context is destroyed)
you should not use any instance variables (as this is not thread-safe)
If your controller scope is request or session, then you can have instance variables, and an instance of the controller is created on each new request/session.

Calling a SLSB with Seam security from a servlet

I have an existing application written in SEAM that uses SEAM Security (http://docs.jboss.org/seam/2.1.1.GA/reference/en-US/html/security.html). In a stateless EJB, I might find something like this:
#In
Identity identity;
...
if(identity.hasRole("admin"))
throw new AuthException();
As far as I understand, Seam injects the Identity object from the SessionContext of the servlet that invokes the EJB (this happens "behind the scenes", since Seam doesn't really use servlets) and removes it after the call. Is this correct?
Is it now possible to access this EJB from another servlet (in this case, that servlet is the server side of a GWT application)? Do I have to "inject" the correct Identity instance? If I don't do anything, Seam injects an instance, but doesn't correctly correlate the sessions and instances of Identity (so the instances of Identity are shared between sessions and sometimes calls get new instances etc.).
Any help and pointers are very welcome - thanks!
Technology: EJB3, Seam 2.1.2. The servlets are actually the server-side of a GWT app, although I don't think this matters much. I'm using JBoss 5.
Seam injects the Identity object from the SessionContext of the servlet that invokes the EJB and removes it after the call. Is this correct ?
Yes, but do not forget you must enable EJB Seam interceptor See here how to
...
Is it now possible to access ANY EJB from another servlet
Yes, you can use its Global JNDI (Vendor dependent) to retrieve it. See here how you can set up and retrieve your EJB #State less / ful bean. If you have a fully-supported Java EE app server, You can retrieve it through annotations.
Do I have to "inject" the correct Identity instance ?
You do not have to worry about it. Seam EJB interceptor Takes care of it. Go ahead.
UPDATE
but in the EJB, two different instances of Identity are injected. I'm guessing the Session context that Seam is using is not correctly linked to the Session context of the servlet ? Any ideas ?
Well, Identity component itself does not implement equals method which, by default, uses default equals implementation by using equals comparison (==). I do not know whether, for each EJB call, you have always a fresh Identity component (Maybe it explains why you have "Two different instances")
If your Servlet's share The same context, you can enable IdentityFilter as a way to wrap your Identity assigned role by using isUserInRole method. Here goes its funcionality:
A filter that provides integration between Servlet Security and the Seam identity component. This integration is accomplished by wrapping the HttpServletRequest with an HttpServletRequestWrapper implementation that delegates security-related calls to the Seam identity component.
If use use #Identity component, it is enabled by default
So instead of inject your EJB (And its #In-jected #Identity) and use
identity.hasRole("admin");
You can use
request.hasUserInRole("admin");
And maybe you want to see Setting and reading the Conversation ID And Seam and GWT
More
The ContextFilter (not enabled by default) opens access to the Seam container and its context variables to non-JSF servlets, such as Struts, Spring MVC, and Direct Web Remoting (DWR). I do not know how to use this kind of funcionality.
Your question is incredibly hard to follow and I'm not sure I understood everything. Anyway, I'll assume you are using Stateless Session Beans (since you said I could use stateful beans) which, by definition, are stateless. So how can Mary get authenticated as Joe after a call to a stateless session bean? This can't be, it doesn't make any sense.
PS: You should maybe rephrase your question and try to clearly distinguish concepts such as the HTTP Session, Session Beans (stateless, stateful?), SessionContext.

Resources