I am reading through head first JSP and servlets. Going through different type of listeners, I came across HttpSessionBindingListener and HttpSessionAttributeListener.
I was thinking about the difference between the two - I want to see the practical usages in real world examples of those two listeners. I tested HttpSessionBindingListener by implementing valueBound() and valueUnBound() - why would an object need to know whether it has been added or not?
I am pretty confused about the practical usages. Please help in clarifying this.
The HttpSessionBindingListener is to be implemented on the class whose instances may be stored in the session, such as the logged-in user.
E.g.
public class ActiveUser implements HttpSessionBindingListener {
#Override
public void valueBound(HttpSessionBindingEvent event) {
logins.add(this);
}
#Override
public void valueUnbound(HttpSessionBindingEvent event) {
logins.remove(this);
}
}
When an instance of this ActiveUser get set as a session attribute by HttpSession#setAttribute(), then the valueBound() will be invoked. When it get removed by either HttpSession#removeAttribute(), or an invalidate of the session, or get replaced by another HttpSession#setAttribute(), then the valueUnbound() will be invoked.
Here are some real world use cases:
Getting SessionScoped bean from HttpSessionListener?
How to call a method before the session object is destroyed?
Call an action when closing a JSP
implementing HttpSessionListener
How to access HTTP sessions in Java
The HttpSessionAttributeListener is to be implemented as an application wide #WebListener which get invoked when any attribute is added, removed or replaced in the HttpSession. Continuing with the above ActiveUser example, this is particularly useful if you can't modify the ActiveUser class to implement HttpSessionBindingListener (because it's 3rd party or so), or when you want to make use of a "marker interface" on an arbitrary amount of classes so that you can do the listening job in a single central place.
#WebListener
public class ActiveUserListener implements HttpSessionAttributeListener {
#Override
public void attributeAdded(HttpSessionBindingEvent event) {
if (event.getValue() instanceof ActiveUser) {
logins.add(event.getValue());
}
}
#Override
public void attributeRemoved(HttpSessionBindingEvent event) {
if (event.getValue() instanceof ActiveUser) {
logins.remove(event.getValue());
}
}
#Override
public void attributeReplaced(HttpSessionBindingEvent event) {
if (event.getValue() instanceof ActiveUser) {
logins.add(event.getValue());
}
}
}
Here's a real world use case:
Getting notification when bounded/unbounded to a HTTP session
Related
Please explain, why self invocation on proxy performed on target but not proxy? If that made on purpose, then why? If proxies created by subclassing, it's possible to have some code executed before each method call, even on self invocation. I tried, and I have proxy on self invocation
public class DummyPrinter {
public void print1() {
System.out.println("print1");
}
public void print2() {
System.out.println("print2");
}
public void printBoth() {
print1();
print2();
}
}
public class PrinterProxy extends DummyPrinter {
#Override
public void print1() {
System.out.println("Before print1");
super.print1();
}
#Override
public void print2() {
System.out.println("Before print2");
super.print2();
}
#Override
public void printBoth() {
System.out.println("Before print both");
super.printBoth();
}
}
public class Main {
public static void main(String[] args) {
DummyPrinter p = new PrinterProxy();
p.printBoth();
}
}
Output:
Before print both
Before print1
print1
Before print2
print2
Here each method called on proxy. Why in documentation mentioned that AspectJ should be used in case of self invocation?
Please read this chapter in the Spring manual, then you will understand. Even the term "self-invocation" is used there. If you still do not understand, feel free to ask follow-up questions, as long as they are in context.
Update: Okay, now after we have established that you really read that chapter and after re-reading your question and analysing your code I see that the question is actually quite profound (I even upvoted it) and worth answering in more detail.
Your (false) assumption about how it works
Your misunderstanding is about how dynamic proxies work because they do not work as in your sample code. Let me add the object ID (hash code) to the log output for illustration to your own code:
package de.scrum_master.app;
public class DummyPrinter {
public void print1() {
System.out.println(this + " print1");
}
public void print2() {
System.out.println(this + " print2");
}
public void printBoth() {
print1();
print2();
}
}
package de.scrum_master.app;
public class PseudoPrinterProxy extends DummyPrinter {
#Override
public void print1() {
System.out.println(this + " Before print1");
super.print1();
}
#Override
public void print2() {
System.out.println(this + " Before print2");
super.print2();
}
#Override
public void printBoth() {
System.out.println(this + " Before print both");
super.printBoth();
}
public static void main(String[] args) {
new PseudoPrinterProxy().printBoth();
}
}
Console log:
de.scrum_master.app.PseudoPrinterProxy#59f95c5d Before print both
de.scrum_master.app.PseudoPrinterProxy#59f95c5d Before print1
de.scrum_master.app.PseudoPrinterProxy#59f95c5d print1
de.scrum_master.app.PseudoPrinterProxy#59f95c5d Before print2
de.scrum_master.app.PseudoPrinterProxy#59f95c5d print2
See? There is always the same object ID, which is no surprise. Self-invocation for your "proxy" (which is not really a proxy but a statically compiled subclass) works due to polymorphism. This is taken care of by the Java compiler.
How it really works
Now please remember we are talking about dynamic proxies here, i.e. subclasses and objects created during runtime:
JDK proxies work for classes implementing interfaces, which means that classes implementing those interfaces are being created during runtime. In this case there is no superclass anyway, which also explains why it only works for public methods: interfaces only have public methods.
CGLIB proxies also work for classes not implementing any interfaces and thus also work for protected and package-scoped methods (not private ones though because you cannot override those, thus the term private).
The crucial point, though, is that in both of the above cases the original object already (and still) exists when the proxies are created, thus there is no such thing as polymorphism. The situation is that we have a dynamically created proxy object delegating to the original object, i.e. we have two objects: a proxy and a delegate.
I want to illustrate it like this:
package de.scrum_master.app;
public class DelegatingPrinterProxy extends DummyPrinter {
DummyPrinter delegate;
public DelegatingPrinterProxy(DummyPrinter delegate) {
this.delegate = delegate;
}
#Override
public void print1() {
System.out.println(this + " Before print1");
delegate.print1();
}
#Override
public void print2() {
System.out.println(this + " Before print2");
delegate.print2();
}
#Override
public void printBoth() {
System.out.println(this + " Before print both");
delegate.printBoth();
}
public static void main(String[] args) {
new DelegatingPrinterProxy(new DummyPrinter()).printBoth();
}
}
See the difference? Consequently the console log changes to:
de.scrum_master.app.DelegatingPrinterProxy#59f95c5d Before print both
de.scrum_master.app.DummyPrinter#5c8da962 print1
de.scrum_master.app.DummyPrinter#5c8da962 print2
This is the behaviour you see with Spring AOP or other parts of Spring using dynamic proxies or even non-Spring applications using JDK or CGLIB proxies in general.
Is this a feature or a limitation? I as an AspectJ (not Spring AOP) user think it is a limitation. Maybe someone else might think it is a feature because due to the way proxy usage is implemented in Spring you can in principle (un-)register aspect advices or interceptors dynamically during runtime, i.e. you have one proxy per original object (delegate), but for each proxy there is a dynamic list of interceptors called before and/or after calling the delegate's original method. This can be a nice thing in very dynamic environments. I have no idea how often you might want to use that. But in AspectJ you also have the if() pointcut designator with which you can determine during runtime whether to apply certain advices (AOP language for interceptors) or not.
Solutions
What you can do in order to solve the problem is:
Switch to native AspectJ, using load-time weaving as described in the Spring manual. Alternatively, you can also use compile-time weaving, e.g. via AspectJ Maven plugin.
If you want to stick with Spring AOP, you need to make your bean proxy-aware, i.e. indirectly also AOP-aware, which is less than ideal from a design point of view. I do not recommend it, but it is easy enough to implement: Simply self-inject a reference to the component, e.g. #Autowired MyComponent INSTANCE and then always call methods using that bean instance: INSTANCE.internalMethod(). This way, all calls will go through proxies and Spring AOP aspects get triggered.
#Dolphin
It is late reply but maybe this text will help you: Spring AOP and self-invocation.
In short, the link leads you to a simple example of why running code from another class will work but from "self" it won't.
Notice looking at the example from the link that when you run code from another class you are asking Spring to inject the bean. And Spring sees that in the bean you are asking for a cache, it creates at runtime proxy for that bean.
On the other hand, when you do the same in the "self" class, you create a compile time method call and Spring won't do anything about it.
In our project we are using aspnetzero template. This template allows a simple but abstracted usage of hangfire. Now we would like to add Hangfire.Console to our project which would allow us to write logs to hangfires dashboard.
In order to write a log statement to the dashboard console we have to access the PerformContext of the current running job. Unfortunately because of the abstraction in aspnetzero we can't inject the PerformContext as it would be planned by hangfire. What we do have access to is the hangfire namespace and all it's static objects.
Therefore my question: Is there a way to get the PerformContext by another way than passing null to the execution method?
What I have tried so far:
By using the IServerFilter interface a method OnPerforming should be called. But unfortunately this is not the case within aspnetzero background jobs.
I tried to overwrite/extend the given base class BackgroundJob< T > of aspnetzero but with no luck. Perhaps someone can give me a hint in this direction.
I used JobFilterAttribute with a IServerFilter.
Example:
[AttributeUsage(AttributeTargets.Class)]
public class HangFirePerformContextAttribute : JobFilterAttribute, IServerFilter
{
private static PerformContext _Context;
public static PerformContext PerformContext
{
get
{
return new PerformContext(_Context);
}
}
public void OnPerformed(PerformedContext filterContext)
{
Context = (PerformContext)filterContext;
_Context = Context;
}
public void OnPerforming(PerformingContext filterContext)
{
Context = (PerformContext)filterContext;
_Context = Context;
}
}
And I create a new Class AsyncBackgroundJobHangFire<TArgs> : AsyncBackgroundJob<TArgs>
Exemple:
[HangFirePerformContext]
public abstract class AsyncBackgroundJobHangFire<TArgs> : AsyncBackgroundJob<TArgs>
{
public PerformContext Context { get; set; }
protected async override Task ExecuteAsync(TArgs args)
{
Context = HangFirePerformContextAttribute.PerformContext;
await ExecuteAsync(args, Context);
}
protected abstract Task ExecuteAsync(TArgs args, PerformContext context);
}
It´s Work
In a Class of job i use a AsyncBackgroundJobHangFire
And de method is
[UnitOfWork]
protected override async Task ExecuteAsync(string args, PerformContext context)
{
}
I have suffered using abp's implementation of hangfire jobs as well. I don't know how to answer your question precisely, but I was able to access a PerformingContext by implementing an attribute that extends JobFilterAttribute and implements IClientFilter, IServerFilter, IElectStateFilter, IApplyStateFilter. The interfaces will depend on your requirements, but I was capable of accessing PerformingContext this way.
You should never use a static field for that, even if marked with a ThreadStaticAttribute , please refer to this link for more details
https://discuss.hangfire.io/t/use-hangfire-job-id-in-the-code/2621/2
Please explain, why self invocation on proxy performed on target but not proxy? If that made on purpose, then why? If proxies created by subclassing, it's possible to have some code executed before each method call, even on self invocation. I tried, and I have proxy on self invocation
public class DummyPrinter {
public void print1() {
System.out.println("print1");
}
public void print2() {
System.out.println("print2");
}
public void printBoth() {
print1();
print2();
}
}
public class PrinterProxy extends DummyPrinter {
#Override
public void print1() {
System.out.println("Before print1");
super.print1();
}
#Override
public void print2() {
System.out.println("Before print2");
super.print2();
}
#Override
public void printBoth() {
System.out.println("Before print both");
super.printBoth();
}
}
public class Main {
public static void main(String[] args) {
DummyPrinter p = new PrinterProxy();
p.printBoth();
}
}
Output:
Before print both
Before print1
print1
Before print2
print2
Here each method called on proxy. Why in documentation mentioned that AspectJ should be used in case of self invocation?
Please read this chapter in the Spring manual, then you will understand. Even the term "self-invocation" is used there. If you still do not understand, feel free to ask follow-up questions, as long as they are in context.
Update: Okay, now after we have established that you really read that chapter and after re-reading your question and analysing your code I see that the question is actually quite profound (I even upvoted it) and worth answering in more detail.
Your (false) assumption about how it works
Your misunderstanding is about how dynamic proxies work because they do not work as in your sample code. Let me add the object ID (hash code) to the log output for illustration to your own code:
package de.scrum_master.app;
public class DummyPrinter {
public void print1() {
System.out.println(this + " print1");
}
public void print2() {
System.out.println(this + " print2");
}
public void printBoth() {
print1();
print2();
}
}
package de.scrum_master.app;
public class PseudoPrinterProxy extends DummyPrinter {
#Override
public void print1() {
System.out.println(this + " Before print1");
super.print1();
}
#Override
public void print2() {
System.out.println(this + " Before print2");
super.print2();
}
#Override
public void printBoth() {
System.out.println(this + " Before print both");
super.printBoth();
}
public static void main(String[] args) {
new PseudoPrinterProxy().printBoth();
}
}
Console log:
de.scrum_master.app.PseudoPrinterProxy#59f95c5d Before print both
de.scrum_master.app.PseudoPrinterProxy#59f95c5d Before print1
de.scrum_master.app.PseudoPrinterProxy#59f95c5d print1
de.scrum_master.app.PseudoPrinterProxy#59f95c5d Before print2
de.scrum_master.app.PseudoPrinterProxy#59f95c5d print2
See? There is always the same object ID, which is no surprise. Self-invocation for your "proxy" (which is not really a proxy but a statically compiled subclass) works due to polymorphism. This is taken care of by the Java compiler.
How it really works
Now please remember we are talking about dynamic proxies here, i.e. subclasses and objects created during runtime:
JDK proxies work for classes implementing interfaces, which means that classes implementing those interfaces are being created during runtime. In this case there is no superclass anyway, which also explains why it only works for public methods: interfaces only have public methods.
CGLIB proxies also work for classes not implementing any interfaces and thus also work for protected and package-scoped methods (not private ones though because you cannot override those, thus the term private).
The crucial point, though, is that in both of the above cases the original object already (and still) exists when the proxies are created, thus there is no such thing as polymorphism. The situation is that we have a dynamically created proxy object delegating to the original object, i.e. we have two objects: a proxy and a delegate.
I want to illustrate it like this:
package de.scrum_master.app;
public class DelegatingPrinterProxy extends DummyPrinter {
DummyPrinter delegate;
public DelegatingPrinterProxy(DummyPrinter delegate) {
this.delegate = delegate;
}
#Override
public void print1() {
System.out.println(this + " Before print1");
delegate.print1();
}
#Override
public void print2() {
System.out.println(this + " Before print2");
delegate.print2();
}
#Override
public void printBoth() {
System.out.println(this + " Before print both");
delegate.printBoth();
}
public static void main(String[] args) {
new DelegatingPrinterProxy(new DummyPrinter()).printBoth();
}
}
See the difference? Consequently the console log changes to:
de.scrum_master.app.DelegatingPrinterProxy#59f95c5d Before print both
de.scrum_master.app.DummyPrinter#5c8da962 print1
de.scrum_master.app.DummyPrinter#5c8da962 print2
This is the behaviour you see with Spring AOP or other parts of Spring using dynamic proxies or even non-Spring applications using JDK or CGLIB proxies in general.
Is this a feature or a limitation? I as an AspectJ (not Spring AOP) user think it is a limitation. Maybe someone else might think it is a feature because due to the way proxy usage is implemented in Spring you can in principle (un-)register aspect advices or interceptors dynamically during runtime, i.e. you have one proxy per original object (delegate), but for each proxy there is a dynamic list of interceptors called before and/or after calling the delegate's original method. This can be a nice thing in very dynamic environments. I have no idea how often you might want to use that. But in AspectJ you also have the if() pointcut designator with which you can determine during runtime whether to apply certain advices (AOP language for interceptors) or not.
Solutions
What you can do in order to solve the problem is:
Switch to native AspectJ, using load-time weaving as described in the Spring manual. Alternatively, you can also use compile-time weaving, e.g. via AspectJ Maven plugin.
If you want to stick with Spring AOP, you need to make your bean proxy-aware, i.e. indirectly also AOP-aware, which is less than ideal from a design point of view. I do not recommend it, but it is easy enough to implement: Simply self-inject a reference to the component, e.g. #Autowired MyComponent INSTANCE and then always call methods using that bean instance: INSTANCE.internalMethod(). This way, all calls will go through proxies and Spring AOP aspects get triggered.
#Dolphin
It is late reply but maybe this text will help you: Spring AOP and self-invocation.
In short, the link leads you to a simple example of why running code from another class will work but from "self" it won't.
Notice looking at the example from the link that when you run code from another class you are asking Spring to inject the bean. And Spring sees that in the bean you are asking for a cache, it creates at runtime proxy for that bean.
On the other hand, when you do the same in the "self" class, you create a compile time method call and Spring won't do anything about it.
We have a lot of code in our code base that's similar to the following interface:
public interface SomethingService {
#Cacheable(value = "singleSomething")
Optional<Something> fetchSingle(int somethingId);
// more methods...
}
This works fine as long we're only using local caches. But as soon as we're using a distributed cache like Hazelcast, things start to break because java.util.Optional<T> is not serializable and thus cannot be cached.
With what I've come up so far to solve this problem:
Removing java.util.Optional<T> from the method definitions and instead checking for the trusty null.
Unwrapping java.util.Optional<T> before caching the actual value.
I want to avoid (1) because it would involve a lot of refactoring. And I have no idea how to accomplish (2) without implementing my own org.springframework.cache.Cache.
What other options do I have? I would prefer a generic (Spring) solution that would work with most distributed caches (Hazelcast, Infinispan, ...) but I would accept a Hazelcast-only option too.
A potential solution would be to register a serializer for the Optional type. Hazelcast has a flexibile serialization API and you can register a serializer for any type.
For more information see the following example:
https://github.com/hazelcast/hazelcast-code-samples/tree/master/serialization/stream-serializer
So something like this:
public class OptionalSerializer implements StreamSerializer<Optional> {
#Override
public void write(ObjectDataOutput out, Optional object) throws IOException {
if(object.isPresent()){
out.writeObject(object.get());
}else{
out.writeObject(null);
}
}
#Override
public Optional read(ObjectDataInput in) throws IOException {
Object result = in.readObject();
return result == null?Optional.empty():Optional.of(result);
}
#Override
public int getTypeId() {
return 0;//todo:
}
#Override
public void destroy() {
}
}
However the solution isn't perfect because this Optional thing will be part of the actual storage. So internally the Optional wrapper is also stored and this can lead to problems with e.g. queries.
I have a requirement whereby I need to advise all delete and save methods and send the deleted/saved record somewhere else.
I am using JpaRepository which has
6 x delete
3 x save
Basically I need to advise all these methods. The trouble is that each of these has different method signatures and return types, sometimes accepting a Long, Object or List. I am considering using aspects to achieve this but it seems that it would be nasty as I currently have 4 objects I need to audit which comes to 4 x 9 = 36 different pointcuts. There are more of these to come so this would soon come into the hundreds.
Is there a better way?
I got it working as #sheltem suggested. I used EntityListeners. In my case I needed access to a spring bean and was able to it this way:
#Component
public class PublishEntityListener {
private static PublishingService publishingService;
#Autowired(
required = true)
public void setPublishingService(PublishingService publishingService) {
this.publishingService = publishingService;
}
#PostConstruct
public void init() {
//Allow the static dependency to be setup post construct as #EntityListeners are no spring managed
}
#PostPersist
public void prePersist(DomainObject<?> entity) {
publishingService.publish(getTopicName(entity), HttpMethod.POST, entity);
}
#PostUpdate
public void preUpdate(DomainObject<?> entity) {
publishingService.publish(getTopicName(entity), HttpMethod.PUT, entity);
}
#PostRemove
public void onDelete(DomainObject<?> entity) {
publishingService.publish(getTopicName(entity), HttpMethod.DELETE, entity);
}
}