- In contextInitialized() method method I have written a code to start the Quartz Scheduler, and since this method will be executed automatically during Servlet container initialization, hence the code for Quartz scheduler job gets invoked, and so it runs for every 10 seconds.
- contextDestroyed() method will be executed when the application shuts down, So in this function I have invoked the shutdown function of quartz scheduler
Struts 2 Push Tag Example
Struts 2 “push” tag is used to push a value into the ValueStack. The value we pushed using push tag will be on top of the ValueStack, so it can be easily referenced using the first-level OGNL expression instead of a deeper reference. The following code show how to do this.
** UPDATE: Struts 2 Complete tutorial now available here.
|
1. Action
package com.simplecode.action; import com.simplecode.util.AuthorBean; //PushTag Action class public class BookInfoAction { private AuthorBean authorBean; public String populate() { authorBean = new AuthorBean ("Mohammed masjid", "Akuland Nz","8051 Micro Controller"); return "populate"; } public String execute() { return "success"; } public AuthorBean getAuthorBean() { return authorBean; } public void setAuthorBean(AuthorBean authorBean) { this.authorBean = authorBean; } }
2. Bean
A simple AuthorBean class, later will push it into the stack for easy access.
package com.simplecode.util; public class AuthorBean { private String name; private String university; private String book; public AuthorBean(String name, String university, String book) { this.name = name; this.university = university; this.book = book; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUniversity() { return university; } public void setUniversity(String university) { this.university = university; } public String getBook() { return book; } public void setBook(String book) { this.book = book; } }
3. Push tag example
It shows the use of “push” tag.
<%@taglib uri="/struts-tags" prefix="s"%> <html> <head> <title>Book Details</title> </head> <body> <p>Author name property can be accessed in two ways:</p> <br /> (Method 1 - Normal method) <br /> <b>Author Name:</b> <s:property value="authorBean.name" /> <br /> <b> University: </b> <s:property value="authorBean.university" /> <br/><b>Book Title :</b> <s:property value="authorBean.book" /> <br /> <br /> (Method 2-push tag) <s:push value="authorBean"> <b>Author Name:</b> <s:property value="name" /> <b> University: </b> <s:property value="university" /> <b>Book Title :</b> <s:property value="book" /> </s:push> </body> </html>
How it work?
Normally, if you want to get the bean’s property, you may reference it like
<s:property value="authorBean.name" />
With “push” tag, you can push the “authorBean” to the top of the stack, and access the property directly
<s:property value="name" />
Both are returned the same result, but with different access mechanism only.
4. Struts.xml
Link it
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="default" extends="struts-default"> <action name="*BookAction" method="{1}" class="com.simplecode.action.BookInfoAction"> <result name="populate">/bookDetails.jsp</result> </action> </package> </struts>
5. Demo
http://localhost:8089/PushTag/populateBookAction.action
Run it
Integrating Quartz Scheduler in Struts 2 Web Application
In our previous article we learn about Quartz 2 hello world example along with types of Triggers in Quartz 2, In this article we shall learn to Integrating Quartz 2 Scheduler in Struts 2 web Application. To know more about Quartz please visit its Official website.
Library required
Commonly Required Struts 2 Jars
commons-logging-1.1.1.jar
log4j-1.2.16.jar
quartz-2.2.1.jar
slf4j-api-1.6.6.jar
slf4j-log4j12-1.6.6.jar
Scheduler Job
Create a Quartz’s job
package com.quartz; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class QuartzJob implements Job { public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("Struts 2 + Quartz 2.2.1"); } }
Servlet Listener
Now Create servlet listener class by implementing ServletContextListener interface and override contextInitialized and contextDestroyed methods with your logic’s.
package com.quartz; import static org.quartz.JobBuilder.newJob; import static org.quartz.TriggerBuilder.newTrigger; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.quartz.CronScheduleBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.impl.StdSchedulerFactory; public class QuartzListener implements ServletContextListener { Scheduler scheduler = null; @Override public void contextInitialized(ServletContextEvent servletContext) { System.out.println("Context Initialized"); try { // Setup the Job class and the Job group JobDetail job = newJob(QuartzJob.class).withIdentity( "CronQuartzJob", "Group").build(); // Create a Trigger that fires every 5 minutes. Trigger trigger = newTrigger() .withIdentity("TriggerName", "Group") .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) .build(); // Setup the Job and Trigger with Scheduler & schedule jobs scheduler = new StdSchedulerFactory().getScheduler(); scheduler.start(); scheduler.scheduleJob(job, trigger); } catch (SchedulerException e) { System.err.println(e.getMessage()); } } @Override public void contextDestroyed(ServletContextEvent servletContext) { System.out.println("Context Destroyed"); try { scheduler.shutdown(); } catch (SchedulerException e) { System.err.println(e.getMessage()); } } }
Recommended Article
web.xml
Configure the listener class QuartzSchedulerListener.java into the web.xml file as shown below
<web-app> <display-name>Quartz 2 + Struts 2</display-name> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class> com.quartz.QuartzListener </listener-class> </listener> </web-app>
Demo
Now on starting the Tomcat Server, the project gets started, and so the listener class QuartzSchedulerListener.java registered in web.xml will be fired, and following logs is obtained at the console
Creating Custom Interceptors in Struts2
In my previous post here I demonstrated about Concepts of Interceptor in Struts 2. In this post we will see how to create a simple interceptor that will execute and print a few lines to the server logs, both before and after an action is executed.
A few points need to be kept in mind before writing your own interceptors;
- You can create your own custom interceptor in two ways
a)Implement the Interceptor interface
b)Extend the AbstractInterceptor class.
- If You are implementing the Interceptor interface, you have to provide implementations to three methods :
void destroy();
void init();
String intercept(ActionInvocation invocation) throws Exception;
- The ‘init’ method is called before the ‘intercept’ method is called. An interceptor instance is created
once and is reused over many requests. Hence the interceptor code must be written to be thread safe.
- The ‘intercept’ is the place where you write the business logic code of your interceptor.
- The ‘destroy’ method is executed on application shutdown and is used to release resources used by the interceptor that have been allocated in the init method
- If you are extending the AbstractInterceptor class, you only need to override the method:
String intercept(ActionInvocation invocation) throws Exception method to provide your own implementation.
- In our example we will be extending the AbstractInterceptor class.
Action Class
Now lets create a dummy action class
package action; import com.opensymphony.xwork2.Action; public class DummyAction implements Action{ public String execute() { System.out.println("Inside Action Class"); return SUCCESS; } }
Interceptors
create two interceptor classes and name it MyInterceptor1 and MyInterceptor2.
File : MyInterceptor1.java
package interceptors; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; public class MyInterceptor1 extends AbstractInterceptor{ @Override public String intercept(ActionInvocation ai) throws Exception { System.out.println("Inside MyInterceptor1- Before Executing Action class"); String invocationResult = ai.invoke(); System.out.println("Inside MyInterceptor1- After Executing Action class"); return invocationResult; } }
File : MyInterceptor2.java
package interceptors; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; public class MyInterceptor2 extends AbstractInterceptor{ @Override public String intercept(ActionInvocation ai) throws Exception { System.out.println("Inside MyInterceptor2- Before Executing Action class"); String invocationResult = ai.invoke(); System.out.println("Inside MyInterceptor2- After Executing Action class"); return invocationResult; } }
Configuring Interceptor in struts.xml
The configuration of struts.xml should be as show below
<struts> <package name="default" extends="struts-default"> <interceptors> <interceptor class="interceptors.MyInterceptor1" name="myInterceptor1"></interceptor> <interceptor class="interceptors.MyInterceptor2" name="myInterceptor2"></interceptor> </interceptors> <action class="action.DummyAction" name="dummyAction"> <interceptor-ref name="myInterceptor1"></interceptor-ref> <interceptor-ref name="myInterceptor2"></interceptor-ref> <result name="success">/success.jsp</result> </action> </package> </struts>
Jsp
File : index.jsp
This file triggers dummyAction during application start up which is used to Test Interceptors
<META HTTP-EQUIV="Refresh" CONTENT="0;URL=dummyAction">
Since the action is already configured such that the two interceptors will be called before and after it is executed, you can check your server logs to ensure that the interceptors are executing in the order as specified in the configuration.
Demo
On running the application, my Tomcat logs show the following :
Inside MyInterceptor1- Before Executing Action class Inside MyInterceptor2- Before Executing Action class Inside Action Class Inside MyInterceptor2- After Executing Action class Inside MyInterceptor1- After Executing Action class
Explanation
Consider the intercept method of MyInterceptor1. This method is called with an argument of type ‘ActionInvocation’. The ActionInvocation object is created by the struts framework and is used as a handle to the execution environment of the interceptor.
Since there are several interceptor defined in struts-default xml, the information of the sequence in which these interceptors are executed for the action is stored in the ActionInvocation object. The next interceptor in the sequence is called by calling the invoke() method of the ActionInvocation object. For the first Interceptor, the invoke() method is called by the ActionProxy object.
Since the invoke method causes the next interceptor/action in the sequence to be executed, the interceptor is in absolute control of the execution and can decide at any moment whether to proceed with the next step in the sequence or to return an error to the caller without proceeding.
Here the String value returned by the invoke() method in Interceptor is the value that is retrieved after the action have been executed. In our example, when the myInterceptor1 interceptor calls it’s invoke, control is passed on to the myInterceptor2, which in turn calls the action. The action upon execution returns “success” as the string, which is in turn returned to the myInterceptor2, which is in turn returned to ‘myInterceptor1′.
I our next article we shall learn to implement an Login interceptor which can be used in a real time application.
Struts 2 + Spring Integration Example
In this following example we shall see how to integrate Spring and Struts 2 using the struts2-spring-plugin. We integrate Spring with Struts2 to utilize the Spring’s Dependency Injection feature.
First add the org.springframework.web.context.ContextLoaderListener to the web.xml file.
** UPDATE: Spring Complete tutorial now available here.
** UPDATE: Struts 2 Complete tutorial now available here.
File : web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Struts2</display-name> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter. StrutsPrepareAndExecuteFilter </filter-class> </filter> <listener> <listener-class>org.springframework.web.context. ContextLoaderListener</listener-class> </listener> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
By default the applicationContext.xml file will be used for doing the Spring bean configuration.
File : applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="helloWorldClass" class="com.simplecode.HelloWorld" > <property name="msg" value="Struts 2 + Spring Integration Example!" /> </bean> </beans>
As you can see we have registered the HelloWorld class and injected the “Hello World!” message to the message attribute using the setter injection method.
All the Struts 2 action configuration goes in the struts.xml file.
File : struts.xml
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="default" extends="struts-default"> <action name="helloWorld" class="helloWorldClass"> <result name="SUCCESS">/success.jsp</result> </action> </package> </struts>
The only change here is instead of referring the com.simplecode.HelloWorld class directly, we relate it using the bean name given in the spring bean configuration file.
The HelloWorld class is shown below. In the execute() method we simply return “SUCCESS” and themessage attribute is set using setter injection.
File : HelloWorld.java
package com.simplecode; public class HelloWorld { private String msg; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public String execute() { return "SUCCESS"; } }
In the index.jsp page we forward the request to the helloWorld action.
<META HTTP-EQUIV="Refresh" CONTENT="0;URL=helloWorld.action">
After invoking the execute() method the user will be directed to the success.jsp page. In this page we dispaly the message value.
You need to have the following jar files in the WEB-INF/lib directory.
commons-fileupload-1.2.1 commons-io-1.3.2 commons-logging-1.1 freemarker-2.3.13 junit-3.8.1 ognl-2.6.11 struts2-convention-plugin-2.1.6 struts2-core-2.1.6 xwork-2.1.2 struts2-spring-plugin-2.1.6 antlr-runtime-3.0 org.springframework.asm-3.0.0.M3 org.springframework.beans-3.0.0.M3 org.springframework.context-3.0.0.M3 org.springframework.core-3.0.0.M3 org.springframework.expression-3.0.0.M3 org.springframework.web-3.0.0.M3 org.springframework.web.servlet-3.0.0.M3
Read More
Struts 2 + Log4j integration example
In this tutorial we will learn about integrate Log4j with Struts 2 framework.
|
Log4j Appender
Create a text file named “log4j.properties“, put it at the root of the project classpath. The log4j.properties or appender file is the Log4j configuration file, it defines how the Log4j logging mechanism work.
** UPDATE: Struts 2 Complete tutorial now available here.
In this example, it will log all the logging detail and outputs it to an external file “C:\\loggerfile.txt“.
log4j.properties
# Direct log messages to a log file log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.File=C:\\loggerfile.txt log4j.appender.file.MaxFileSize=10MB log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n # Direct log messages to stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n # Root logger option log4j.rootLogger=warn, file, stdout
Action Class
To use Log4j in Struts 2 framework, you can get the Log4j logger via Logger.getLogger() and log it directly.
package com.simplecode.action; import org.apache.log4j.Logger; import com.opensymphony.xwork2.ActionSupport; public class LoggerAction extends ActionSupport { private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(LoggerAction.class); public String execute() throws Exception { logger.warn("Warning ......."); logger.error("Error ......."); return SUCCESS; } }
Demo
Now, all the logging details will be logged into the file, named “C:\\loggerfile.txt“. See sample :
23:37:38,166 ERROR LoggerAction:15 – Error …….
|
Reference
Read More
How to exclude action methods from validation in struts2
My Action class have the following methods,
1.addAction
2.deleteAction
3.updateAction
4.populateAction
** UPDATE: Struts 2 Complete tutorial now available here.
Consider a scenario where I want to apply validation for addAction and deleteAction method alone and not for other method , then all you to do a configuration in struts.xml file by listing all the methods you don’t want to be run through the validation framework in the excludeMethods parameter. Since we only want addElement and deleteElement validated, list the other two methods as follows:
<interceptor-ref name="validation"> <param name="excludeMethods">updateAction,populateAction</param> </interceptor-ref>
Read More