Interceptor in JSF - jsf

I want to know if there is an interceptor in JSF (like we use in Spring), and how to do we implement it?

You could implement a PhaseListener for this. You could program them to listen on a specific JSF phase which you specify in the overridden getPhaseId() method. You can intercept on the before and after phase events by beforePhase() and afterPhase() methods.
The below example listens on the render response phase:
public class RequestInterceptor implements PhaseListener {
#Override
public PhaseId getPhaseId() {
return PhaseId.RENDER_RESPONSE;
}
#Override
public void beforePhase(PhaseEvent event) {
// Do your job here which should run before the render response phase.
}
#Override
public void afterPhase(PhaseEvent event) {
// Do your job here which should run after the render response phase.
}
}
To get it to run, you need to register it as a <phase-listener> in the <life-cycle> section of the faces-config.xml file. You can have multiple <phase-listener>s.
<lifecycle>
<phase-listener>com.example.RequestInterceptor</phase-listener>
</lifecycle>
You can specify PhaseId.ANY_PHASE in getPhaseId() to let the phase listener run on every single JSF phase (note that not necessarily all of them will always be executed, that depends on the request type). You can if necessary get the current phase ID in the before and after phase methods by PhaseEvent#getPhaseId().
public class PhaseDebugger implements PhaseListener {
#Override
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
#Override
public void beforePhase(PhaseEvent event) {
System.out.println("Before phase " + event.getPhaseId());
}
#Override
public void afterPhase(PhaseEvent event) {
System.out.println("After phase " + event.getPhaseId());
}
}
Alternatively, a Filter should work equally good if you want a more global hook (and thus you're not exactly interested in JSF requests/responses and you do not need anything from the FacesContext).
#WebFilter("/*")
public class RequestInterceptor implements Filter {
#Override
public void init(FilterConfig config) {
// Initialize global variables if necessary.
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
// Do your job here which should run before the request processing.
chain.doFilter(request, response);
// Do your job here which should run after the request processing.
}
#Override
public void destroy() {
// Cleanup global variables if necessary.
}
}

Related

Jboss logger clear MDC during thread lifecycle

I need to improve logging in a JavaEE application running on wildfly using jboss logger & logstash, I'm using MDC to store userID but as I'm new with thread usage I'm not figuring out how to clear the MDC before a thread is recycled
I have found different ways to clear the MDC but I think I am missing some pieces of knowledge regarding threads ... :
I've tried to extend Thread :
public class MdcThread extends Thread {
LoggingTools loggingTools = new LoggingTools(MdcThread.class);
#Override
public void run() {
loggingTools.info("MdcThread");
MDC.clear();
}
}
I've tried to extend ThreadPoolExecutor :
public class MdcThreadPoolExecutor extends ThreadPoolExecutor {
static LoggingTools loggingTools = new LoggingTools(MdcThreadPoolExecutor.class);
...constructors...
#Override
public void execute(Runnable command) {
super.execute(wrap(command));
}
public static Runnable wrap(final Runnable runnable) {
return new Runnable() {
#Override
public void run() {
try {
runnable.run();
} finally {
loggingTools.info("Mdc clear");
MDC.clear();
}
}
};
}
}
But none of these are called ... So I assume ThreadPoolExecutor is a way of using thread but not necessarily used? how can I reach the lifecycle of the threads?
EDIT :
Here is the filter I've used :
#WebFilter("/*")
public class MdcFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (request != null) {
//add what I want in MDC
}
chain.doFilter(request, response);
}
#Override
public void destroy() {
MDC.clear();
}
}
If you're using logback then WildFly or JBoss Log Manager will not be managing MDC. Most implementations of MDC, and I assume you're using org.slf4j.MDC since you're using logback, are thread locals so MDC.clear() will only clear the map on that threads MDC map. Have a look at slf4j's MDC manual.
If you want to clear the message diagnostic context you need to do it in the same thread that adds that adds the data you want cleared.

How to thread-safely share an attribute between the beforePhase() and the afterPhase() methods of a PhaseListener?

I need to share an attribute between the beforePhase() and the afterPhase() methods of my PhaseListener, for a same JSF request.
Is the following snippet thread-safe?
public class MyPhaseListener implements PhaseListener {
private MyObject o = null;
#Override
public void beforePhase(PhaseEvent event) {
if (condition) {
o = new MyObject();
}
}
#Override
public void afterPhase(PhaseEvent event) {
if (o != null) {
o.process();
o = null;
}
}
#Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}
If not, what are other solutions?
This is definitely not threadsafe. There's only one phase listener instance applicationwide which is shared across multiple requests. Basically, a phase listener is like an #ApplicationScoped managed bean.
Just set it as a context attribute.
public class MyPhaseListener implements PhaseListener {
#Override
public void beforePhase(PhaseEvent event) {
if (condition) {
event.getFacesContext().setAttribute("o", new MyObject());
}
}
#Override
public void afterPhase(PhaseEvent event) {
MyObject o = (MyObject) event.getFacesContext().getAttribute("o");
if (o != null) {
o.process();
}
}
#Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}
You could use ThreadLocal for this, but it tends to have issues in environments having different classloaders, to name it: memory leak. Be sure to check for that in the given environment...
Also, you should make it sure that if the processing can be interrupted (e.g. exception...) between the beforePhase() and afterPhase() methods, the ThreadLocal should be handled appropriately...
This is what it would look like:
public class MyPhaseListener implements PhaseListener {
//if null is a valid value, no initial setting is needed
private ThreadLocal<Object> myStateObject = new ThreadLocal<Object> ();
#Override
public void beforePhase(PhaseEvent event) {
//might be needed, to guarrantee no residue from an aborted processing is in there
myState.set(null);
if (condition) {
myState.set(<Object representing the state>);
}
}
#Override
public void afterPhase(PhaseEvent event) {
try {
Object stateObject = myState.get();
if (stateObejct!=null) {
//do what you have to
}
} finally {
//to be sure
myState.remove();
}
}
}
In this article the author uses ThreadLocal too...
Also, this article is also a great eye-opener, explaining why not to share mutable instance-level information:
One thing to remember though, is that PhaseListener instances are application-wide Singletons that are referenced by the JSF Lifecycle, which itself is an application-wide Singleton.
EDIT just saw Boolean got updated to Object, adjusted example

JSF 2 equivalent of IBM's hx:scriptCollector pre- and postRender

I am migrating an old JSF application from WebSphere to JBoss: the old version uses an IBM implementation of JSF. My question concerns the following component:
<hx:scriptCollector id="aScriptCollector"
preRender="#{aBean.onPageLoadBegin}" postRender="#{aBean.onPageLoadEnd}">
To reproduce the preRender behavior in JSF 2 I use a binding for the form (s. here). My questions:
1) Do you know a trick for simulating postRender in JSF 2?
2) Do you think is the trick I am using for preRender "clean"?
Thanks a lot for your help!
Bye
Closest what you can get to achieve exactly the same hooks is
<f:view beforePhase="#{bean.beforePhase}" afterPhase="#{bean.afterPhase}">
with
public void beforePhase(PhaseEvent event) {
if (event.getPhaseId == PhaseId. RENDER_RESPONSE) {
// ...
}
}
public void afterPhase(PhaseEvent event) {
if (event.getPhaseId == PhaseId. RENDER_RESPONSE) {
// ...
}
}
The preRender can be achieved in an easier manner, put this anywhere in your view:
<f:event type="preRenderView" listener="#{bean.preRenderView}" />
with
public void preRenderView(ComponentSystemEvent event) {
// ...
}
(the argument is optional, you can omit it if never used)
There's no such thing as postRenderView, but you can easily create custom events. E.g.
#NamedEvent(shortName="postRenderView")
public class PostRenderViewEvent extends ComponentSystemEvent {
public PostRenderViewEvent(UIComponent component) {
super(component);
}
}
and
public class PostRenderViewListener implements PhaseListener {
#Override
public PhaseId getPhaseId() {
return PhaseId.RENDER_RESPONSE;
}
#Override
public void beforePhase(PhaseEvent event) {
// NOOP.
}
#Override
public void afterPhase(PhaseEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().publishEvent(context, PostRenderViewEvent.class, context.getViewRoot());
}
}
which you register in faces-config.xml as
<lifecycle>
<phase-listener>com.example.PostRenderViewListener</phase-listener>
</lifecycle>
then you can finally use
<f:event type="postRenderView" listener="#{bean.postRenderView}" />
with
public void postRenderView(ComponentSystemEvent event) {
// ...
}

FacesMessage listener

What is the way for debugging JSF messages.
Can I implement some listener and catch all error messages that JSF is about to display?
You could with a PhaseListener hook on the beforePhase() of the PhaseId.RENDER_RESPONSE.
E.g.
public class MessagesListener implements PhaseListener {
#Override
public PhaseId getPhaseId() {
return PhaseId.RENDER_RESPONSE;
}
#Override
public void beforePhase(PhaseEvent event) {
Iterator<FacesMessage> messageIterator = event.getFacesContext().getMessages();
while (messageIterator.hasNext()) {
FacesMessage message = messageIterator.next();
// ...
}
}
#Override
public void afterPhase(PhaseEvent event) {
// NOOP.
}
}
To get it to run, register it as follows in faces-config.xml:
<lifecycle>
<phase-listener>com.example.MessagesListener</phase-listener>
</lifecycle>

How to intercept request ends?

Hi in JSF i need to perform some action when each request of the user ends. I need some kind of interceptor but i don't know how to do it. I need help with this please. Thanks
I recommend BalusC's blog: http://balusc.blogspot.com/2006/09/debug-jsf-lifecycle.html
This article shows you how to intercept the JSF lifecycle and debug the information. This will also make it available for you to find out where your request ends.
If you posted some code here it could also help us find out where the true problem lies.
Here is an excerpt of the code that you need to implement to debug the lifecycle:
package mypackage;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
public class LifeCycleListener implements PhaseListener {
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
public void beforePhase(PhaseEvent event) {
System.out.println("START PHASE " + event.getPhaseId());
}
public void afterPhase(PhaseEvent event) {
System.out.println("END PHASE " + event.getPhaseId());
}
}
If you want to have the FacesContext available, then the best place is the afterPhase of PhaseID.RENDER_RESPONSE inside a PhaseListener. For example:
public class MyPhaseListener implements PhaseListener {
public PhaseId getPhaseId() {
return PhaseId.RENDER_RESPONSE;
}
public void beforePhase(PhaseEvent event) {
// No operation here.
}
public void afterPhase(PhaseEvent event) {
FacesContext context = event.getFacesContext();
// Do your thing here with the FacesContext.
}
}
If you don't need the FacesContext, then the best place is after the line chain.doFilter(request, response) inside a Filter. For example:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
chain.doFilter(request, response);
// Do your thing here.
}

Resources