Main idea is to use JSF with Spring AOP for modularizing cross cutting concerns like logging.
I am using STS (Spring tool suite) and have jsp page with jsf tags. These tags are reading data from a managed bean properties(getter). I have aspect configured for the getters. When i run application with Java/AspectJ getter is called and aspect advice code is executed and it prints out using system.out.println a message to console.
But when i load jsf page there is no output on the console.
Any idea how can i integrate these aspects with calls from JSF or JSP pages ?
R – STS : Using JSF , Managed beans and Aspects
aopjsfspring
Related Solutions
JSP (JavaServer Pages)
JSP is a Java view technology running on the server machine which allows you to write template text in client side languages (like HTML, CSS, JavaScript, ect.). JSP supports taglibs, which are backed by pieces of Java code that let you control the page flow or output dynamically. A well-known taglib is JSTL. JSP also supports Expression Language, which can be used to access backend data (via attributes available in the page, request, session and application scopes), mostly in combination with taglibs.
When a JSP is requested for the first time or when the web app starts up, the servlet container will compile it into a class extending HttpServlet
and use it during the web app's lifetime. You can find the generated source code in the server's work directory. In for example Tomcat, it's the /work
directory. On a JSP request, the servlet container will execute the compiled JSP class and send the generated output (usually just HTML/CSS/JS) through the web server over a network to the client side, which in turn displays it in the web browser.
Servlets
Servlet is a Java application programming interface (API) running on the server machine, which intercepts requests made by the client and generates/sends a response. A well-known example is the HttpServlet
which provides methods to hook on HTTP requests using the popular HTTP methods such as GET
and POST
. You can configure HttpServlet
s to listen to a certain HTTP URL pattern, which is configurable in web.xml
, or more recently with Java EE 6, with @WebServlet
annotation.
When a Servlet is first requested or during web app startup, the servlet container will create an instance of it and keep it in memory during the web app's lifetime. The same instance will be reused for every incoming request whose URL matches the servlet's URL pattern. You can access the request data by HttpServletRequest
and handle the response by HttpServletResponse
. Both objects are available as method arguments inside any of the overridden methods of HttpServlet
, such as doGet()
and doPost()
.
JSF (JavaServer Faces)
JSF is a component based MVC framework which is built on top of the Servlet API and provides components via taglibs which can be used in JSP or any other Java based view technology such as Facelets. Facelets is much more suited to JSF than JSP. It namely provides great templating capabilities such as composite components, while JSP basically only offers the <jsp:include>
for templating in JSF, so that you're forced to create custom components with raw Java code (which is a bit opaque and a lot of tedious work) when you want to replace a repeated group of components with a single component. Since JSF 2.0, JSP has been deprecated as view technology in favor of Facelets.
Note: JSP itself is NOT deprecated, just the combination of JSF with JSP is deprecated.
Note: JSP has great templating abilities by means of Taglibs, especially the (Tag File) variant. JSP templating in combination with JSF is what is lacking.
As being a MVC (Model-View-Controller) framework, JSF provides the FacesServlet
as the sole request-response Controller. It takes all the standard and tedious HTTP request/response work from your hands, such as gathering user input, validating/converting them, putting them in model objects, invoking actions and rendering the response. This way you end up with basically a JSP or Facelets (XHTML) page for View and a JavaBean class as Model. The JSF components are used to bind the view with the model (such as your ASP.NET web control does) and the FacesServlet
uses the JSF component tree to do all the work.
Related questions
- What is the main-stream Java alternative to ASP.NET / PHP?
- Java EE web development, what skills do I need?
- How do servlets work? Instantiation, session variables and multithreading
- What is a Javabean and where are they used?
- How to avoid Java code in JSP files?
- What components are MVC in JSF MVC framework?
- What is the need of JSF, when UI can be achieved with JavaScript libraries such as jQuery and AngularJS
Let's imagine you want to log the time taken by some annoted methods using a @LogExecTime
annotation.
I first create an annotation LogExecTime
:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecTime {
}
Then I define an aspect:
@Component // For Spring AOP
@Aspect
public class LogTimeAspect {
@Around(value = "@annotation(annotation)")
public Object LogExecutionTime(final ProceedingJoinPoint joinPoint, final LogExecTime annotation) throws Throwable {
final long startMillis = System.currentTimeMillis();
try {
System.out.println("Starting timed operation");
final Object retVal = joinPoint.proceed();
return retVal;
} finally {
final long duration = System.currentTimeMillis() - startMillis;
System.out.println("Call to " + joinPoint.getSignature() + " took " + duration + " ms");
}
}
}
I create a class annoted with LogExecTime
:
@Component
public class Operator {
@LogExecTime
public void operate() throws InterruptedException {
System.out.println("Performing operation");
Thread.sleep(1000);
}
}
And a main using Spring AOP:
public class SpringMain {
public static void main(String[] args) throws InterruptedException {
ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
final Operator bean = context.getBean(Operator.class);
bean.operate();
}
}
If I run this class I'm getting the following output on stdout:
Starting timed operation
Performing operation
Call to void testaop.Operator.Operate() took 1044 ms
Now with the magic. As I did use Spring AOP rather than AspectJ weaver, the magic is occurring at run time using proxy-ish mechanisms. So the .class
files are left untouched. For instance if I debug this program and put a breakpoint in operate
you'll see how Spring has performed the magic:
As Spring AOP implementation is non-intrusive and uses the Spring mechanisms you need to add the @Component
annotation and create the object using Spring context rather than plain new
.
AspectJ on the other side will change the .class
files. I tried this project with AspectJ and decompiled the Operator class with jad. Which lead to:
public void operate()
throws InterruptedException
{
JoinPoint joinpoint = Factory.makeJP(ajc$tjp_0, this, this);
operate_aroundBody1$advice(this, joinpoint, LogTimeAspect.aspectOf(), (ProceedingJoinPoint)joinpoint, (LogExecTime)(ajc$anno$0 == null && (ajc$anno$0 = testaop/Operator.getDeclaredMethod("operate", new Class[0]).getAnnotation(testaop/LogExecTime)) == null ? ajc$anno$0 : ajc$anno$0));
}
private static final void operate_aroundBody0(Operator ajc$this, JoinPoint joinpoint)
{
System.out.println("Performing operation");
Thread.sleep(1000L);
}
private static final Object operate_aroundBody1$advice(Operator ajc$this, JoinPoint thisJoinPoint, LogTimeAspect ajc$aspectInstance, ProceedingJoinPoint joinPoint, LogExecTime annotation)
{
long startMillis = System.currentTimeMillis();
Object obj;
System.out.println("Starting timed operation");
ProceedingJoinPoint proceedingjoinpoint = joinPoint;
operate_aroundBody0(ajc$this, proceedingjoinpoint);
Object retVal = null;
obj = retVal;
long duration = System.currentTimeMillis() - startMillis;
System.out.println((new StringBuilder("Call to ")).append(joinPoint.getSignature()).append(" took ").append(duration).append(" ms").toString());
return obj;
Exception exception;
exception;
long duration = System.currentTimeMillis() - startMillis;
System.out.println((new StringBuilder("Call to ")).append(joinPoint.getSignature()).append(" took ").append(duration).append(" ms").toString());
throw exception;
}
private static void ajc$preClinit()
{
Factory factory = new Factory("Operator.java", testaop/Operator);
ajc$tjp_0 = factory.makeSJP("method-execution", factory.makeMethodSig("1", "operate", "testaop.Operator", "", "", "java.lang.InterruptedException", "void"), 5);
}
private static final org.aspectj.lang.JoinPoint.StaticPart ajc$tjp_0; /* synthetic field */
private static Annotation ajc$anno$0; /* synthetic field */
static
{
ajc$preClinit();
}
Best Answer
If you are using
and the managed beans are part of the spring-context (either via the
@Controller
annotation, or inapplicationContext.xml
), the aspects should work with them.