Java Frameworks

WebWorks

quick tutorial

http://www.opensymphony.com/webwork/wikidocs/Tutorial.html

how does it work

com.opensymphony.webwork.dispatcher.FilterDispatcher

http://www.opensymphony.com/webwork/api/com/opensymphony/webwork/dispatcher/FilterDispatcher.html

This filter executes actions by consulting the ActionMapper and determining if the requested URL should invoke an action. If the mapper indicates it should, the rest of the filter chain is stopped and the action is invoked. This is important, as it means that filters like the SiteMesh filter must be placed before this filter or they will not be able to decorate the output of actions.

src access : http://kickjava.com/src/com/opensymphony/webwork/dispatcher/FilterDispatcher.java.htm
line 145: public void doFilter(…)

then in DispatcherUtils.java, public void serviceAction(…) is called.
http://kickjava.com/src/com/opensymphony/webwork/dispatcher/DispatcherUtils.java.htm

filters

http://www.orionserver.com/tutorials/filters/3.html

public void doFilter(final ServletRequest request, final ServletResponse response, FilterChain chain) throws IOException, ServletException 
{           
           GenericResponseWrapper wrapper = new GenericResponseWrapper((HttpServletResponse) response); 
           chain.doFilter(request, wrapper); 
           byte[] data = wrapper.getData();
 
       //manipulate the byte[] data
       ...
 
       OutputStream out = response.getOutputStream(); 
           out.write(data); 
           out.close(); 
}

http://www.javaworld.com/javaworld/jw-06-2001/jw-0622-filters.html?page=1

MIME

http://en.wikipedia.org/wiki/MIME#Multipart_messages

MIME-Version: 1.0
Content-type: multipart/mixed; boundary="frontier"

This is a message with multiple parts in MIME format.
--frontier
Content-type: text/plain

This is the body of the message.
--frontier
Content-type: application/octet-stream
Content-transfer-encoding: base64

PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg
Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==
--frontier--

HTTP with multipart/form-data

http://www.mime-rpc.com/examples.html
http://www.redmountainsw.com/wordpress/archives/multipartform-data-over-the-wire-example

Request:

POST /some/resource HTTP/1.1
Content-type: multipart/form-data, boundary=AaB03x

--AaB03x
content-disposition: form-data; name="field1"

Joe Blow
--AaB03x
content-disposition: form-data; name="pics"; filename="file1.gif"
Content-type: image/gif
Content-Transfer-Encoding: binary

...contents of file1.gif...
 --AaB03x--

Response:

HTTP/1.0 200 OK
Content-type: text/plain

OK

struts

Struts 2 has a single runtime configuration that’s built up in the following order:
1 struts-default.xml (bundled in the struts2-core-x.y.z.jar)
2 struts-plugin.xml (as many as can be found in plug-in JARs)
3 struts.xml (provided by your application)

root namespace vs empty namespace

Note that the default namespace is actually the empty string "". You can also define a root namespace such as "/". The root namespace is treated as all other explicit namespaces and must be matched. It’s important to distinguish between the empty default namespace, which can catch all request patterns as long as the action name matches, and the root namespace, which is an actual namespace that must be matched.

basic stack vs default stack

Incidentally, the basicStack, not to be confused with the default defaultStack, is just a convenient chunk of common interceptors that the struts-default package makes available to you to ease the process of custom stack building in case you find that the defaultStack isn’t quite what you need.

<interceptor-stack name="basicStack">
  <interceptor-ref name="exception"/>
  <interceptor-ref name="servletConfig"/>
  <interceptor-ref name="prepare"/>
  <interceptor-ref name="checkbox"/>
  <interceptor-ref name="params"/>
  <interceptor-ref name="conversionError"/>
</interceptor-stack>

ActionInvocation

we call it a recursive process. Let’s have a look. The framework itself starts the process by making the first call to the ActionInvocation object’s invoke()
method. ActionInvocation hands control over to the first interceptor in the stack by calling that interceptor’s intercept() method. Importantly, intercept() takes the
ActionInvocation instance itself as a parameter. During its own processing, the interceptor will call invoke() on this object to continue the recursive process of invoking
successive interceptors. Thus, in normal execution, the invocation process tunnels down through all of the interceptors until, finally, there are no more interceptors in
the stack and the action fires. Again, the ActionInvocation itself maintains the state of this process internally so it always knows where it is in the stack.

Interceptor: http://www.koders.com/java/fid52BFCB69561E9A4164941EF51F3309436E31753B.aspx?s=doIntercept#L66
DefaultInvocationFactory : http://www.koders.com/java/fidA9C7216E419B7311CD5A8B992C714E1E534F87C4.aspx
DefaultActionInvocation: http://www.koders.com/java/fid052C33E0300EF17B1A639E6189C7D81B00BB0D8F.aspx?s=DefaultActionInvocation#L12
DefaultWorkflowInterceptor: http://www.koders.com/java/fidA982537AD91125E0DC4C42B402A9C4FA98BB7F9F.aspx?s=TimerInterceptor

Interceptors

while actions that don’t define any interceptor-refs themselves will inherit the default interceptors, as soon as an action declares its own interceptors, it loses that automatic default and must explicitly name the defaultStack in order to use it.

Interceptor instances are shared among actions. Though a new instance of an action is created for each request, interceptors are reused. This has one important implication. Interceptors are stateless. Don’t try to store data related to the request being processed on the interceptor object.

type converter

Instead of using the ActionClassName-conversion.properties file to configure your type converter, use xwork-conversion.properties. As you can probably tell, this is just
a global version of the conversion properties. the xwork-conversion.properties file goes on the classpath, such as in WEB-INF/classes/.

result

result types

AJAX Result type

<result-types>
  <result-type name="customJSON" class="manning.chapterEight.JSONResult" />
</result-types>
<action name="AjaxRetrieveUser" class="manning.chapterEight.RetrieveUser">
  <result type="customJSON">artist</result>
</action>

redirect and include

RequestDispatcher
<result>/chapterEight/VisitorHomePage.jsp</result>

It would be valid, but unnecessary, to specify the location property with an explicit param tag as follows:

<result type="dispatcher">
  <param name="location">/chapterEight/VisitorHomePage.jsp</param>
</result>

Thanks to the framework’s dedication to intelligent defaults, we can usually avoid such lengthy elements in our declarative architecture documents.
Note that we also added the unnecessary type attribute here. It’s unnecessary because the RequestDispatcher is the default result type as long as you inherit from
the struts-default package. and the framework also defines DEFAULT_PARAM as location.

The RequestDispatcher exposes two methods for handing execution over to the other servlet: include() and forward(). These two methods determine how much control over the response will be given to the secondary resource. the include() method means that the first servlet has already started writing its own response to the client but wants to include the output from the second servlet in that response. A permanent handoff is done via a call to the forward() method. In this case, the first servlet must not have sent any response to the client before the call is made. In a forward, the servlet is delegating the complete response rendering to the second servlet.

These two dispatch methods are quite different from each other, but they do share some things in common. Most importantly, they’re both distinguished from an HTTP redirection. Whereas a redirection sends the browser a redirect response telling it to make another request to a different URL, the dispatcher methods don’t send the browser any response at all. The transfer of control, from one resource to another, is completely within the server. In fact, it’s even in the same thread of execution. Another important detail is that the include() and forward() methods both pass the original request and response objects to the new servlet. This important detail allows the second servlet to essentially process the same request.

redirect from server side(to be acurate, it should be called forward)

Let’s consider the normal Struts 2 workflow from a Servlet perspective. By normal workflow, we mean the simple case where an action receives the request, processes the business logic, prepares the data, then asks a result to render the response.

First of all, note that the framework is itself actually just a servlet. Well, a servlet filter. When the framework first processes a request, we can consider it as the work of the primary servlet. Thus, when your initial action is executing, it’s executing as the primary servlet. When it’s finished, the action selects a JSP result to render the view. Since JSP pages are actually servlets, this transfer of execution from the action to the JSP page is a transfer of control from the first servlet to a second. This normal case is done with the Request-Dispatcher’s forward() method.

This implies that the Struts 2 action, processing under the control of the first servlet, obviously can’t have written anything to the response yet.( If it had, we’d be limited to an include() call). By forwarding to the result JSP servlet, the action gives full control over writing the response to that JSP. the JSP has access to all of the data from the action via the ThreadLocal ActionContext, and its most important citizen, the ValueStack; this access to the ActionContext depends on the fact that the dispatching of requests always occurs on the same thread of execution.

This is the low-level expression of the framework’s MVC separation of concerns.

include on server side

The main reason is because included material must make sense as a fragment, since it’s dumped midstream into the primary response.

action tag

Here’s an example that chooses to include the secondary action’s result:

<h3>Action Tag</h3>
<h4>This line is from the ActionTag action's result.</h4>
<s:action name="TargetAction" executeResult="true"/>
include tag

this tag allows you to execute a Servlet API–style include. This means you can include the output of another web resource in the currently rendering page. One good thing about the Struts 2 include tag is that it allows you to pass along request parameters to the included resource.

This differs from the previously seen action tag, in that the include tag can reference any servlet resource, while the action tag can include only another Struts 2
action within the same Struts 2 application. This inclusion of an action stays completely within the Struts 2 architecture. The include tag can go outside of the Struts 2
architecture to retrieve any resource available to the web application in which the Struts 2 application is deployed.

the advantages to choosing the Struts 2 include tag over the native JSP version are:
1) support parameters.
2) The Struts 2 include tag will rewrite ../index.jsp as an absolute URL based on the current URL where the JSP is located.

redirect from browser

The defining characteristic of the RequestDispatcher is that the handoff is completely on the server side. A redirect, on the other hand, considers the current request finished and issues an HTTP redirect response that tells the browser to point to a new location. This act officially closes the current request from both the Struts 2 ActionContext perspective and the Servlet request perspective. In other words, all server-side request- and actionrelated state is gone.

The most common reason for using a redirect arises from the need to change the URL shown in the browser. When a redirect is issued, the browser handles the response by making a new request to the URL given in the redirect. The URL to which the redirect is issued replaces the previous URL in the browser

a redirect result type
<action name="SendUserToSearchEngineAction" class="myActionClass">
<result type='redirect'>http://www.google.com</result>
</action>
a redirect by redirectAction
<action name="Login" class="manning.chapterEight.Login">
  <result type="redirectAction">
     <param name="actionName">AdminPortfolio</param>
     <param name="namespace">/chapterEight/secure</param>
  </result>
  <result name="input">/chapterEight/Login.jsp</result>
</action>

- The redirectAction result does the same thing as the plain redirect result, however you don’t have to embed real URLs in your result declarations. Instead you can feed the redirectAction names and namespaces from your action and package declarations. This makes your declarations more robust in the face of changes to URL patterns. As an example of such a URL pattern change, let’s say you wanted to change the action extension from .action to .go. If you’d used the plain redirect result extensively to target Struts 2 actions, then you’d have a lot of hard-coded URLs to adjust.
- We can easily configure request parameters to be passed on to the target action. With the plain redirect, we had to write the querystring parameter out by hand.

validate

you could use both forms of validation at the same time, if you like. First, the validation interceptor runs all validations that you define with the validation framework metadata. Then, when the workflow interceptor runs, it still checks to see if your action implements the validate() method. Even if you’ve already run some validators via the validation interceptor, you can still provide some additional validation code in a validate() method.

view

localization:

■ ActionClassName.properties : for localized text
■ ActionClassName_es.properties : for special languages

validators:

■ SuperClassName-validation.xml
■ SuperClassName-aliasName-validation.xml
■ InterfaceName-validation.xml
■ InterfaceName-aliasName-validation.xml
■ ActionClassName.validations.xml : for validators
■ ActionClassName-aliasName-validation.xml : for different actions that share the same class
■ validators.xml : for custom validators

i18n

<s:text name="homepage.greeting"/>

is equivalent to :

<s:property value="getText('homepage.greeting')"/>

The key is used to do the label, and the name value is used for binding the component to the data transfer, and so on.if your tag doesn’t specify a name attribute, the key itself is used as a name attribute.

<s:label key="user.username" />

<s:textfield key="user.firstName"/>
<message key="email.invalid"/>

searching order

  1. ActionClassName_es_SP.properties,ActionClassName_es.properties
  2. ActionClassImplementedInterfaceName_es.properties
  3. ActionClassSuperClassName_es.properties
  4. ModelClassName_es.properties
  5. package.properties
  6. Domain model object exposed on the ValueStack referenced by key—
  7. default

for conversion error message :

invalid.fieldvalue.xxx = …

explicitly define a bundle

<s:i18n name="manning.chapterEleven.SpecialMessages">
  <s:text name="greeting"/>
</s:i18n>

wild card matching

Finally, there are some things to remember regarding wildcard mapping:
• There is a limit of nine text groups, {1} through {9}.
• The token {0} is special and contains the entire URL requested.
• The * token will match 0 or more characters, excluding the “/” character.
• The ** token will match 0 or more characters, including the “/” character.
• The “\” character is used as an escape sequence to punctuation characters, thus \\
matches the “\” character, and \* matches the “*” character.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License