Monday, September 17, 2012
Blog Three Year Anniversary
Thursday, July 26, 2012
Various Ways for Navigation in JSF 2(draft)
- Use the following:
<h: button outcome="xyz" .../>
The web will go directly xyz.xhtml. The URL in the browser is changed to something like ***/xyz.jsf - Use the following:
<h:commandButton action="xyz" ... />
Go to faces-config.xml to look for the <from-outcome> match for this page. The value in the <to-view-id> tag will be used and the the URL will be changed accordingly. - Use the following:
<h:commandButton action="#{bean.method}" ... />Invoke the method of the bean. The return value is a string.- The returned result is the following "abc?faces-redirect=true". In this case, the web will go to abc.xhtml. The URL is changed.
- The returned result is the following "abc". In this case, the web will show the content of abc.xhtml. But the URL will not change. So if the current page is xyz.xhtml, the new URL will still be xyz.xhtml instead of abc.xhtml.
Note that this case of using bean method for the 'action' attribute in h:commandButton is syntactically the same as the case of using string literal for the 'action' attribute in h:commandButton. So maybe the navigation rule is the same. The navigation will first look for the match in faces-config.xml. If a match is not found, then it will just use the value of the 'action' attribute as the page name. It will either redirect to it or forward to it depending on the redirect flag.
-
<h:commandButton listener="#{bean.method}" ... />or<h:commandButton actionListener="#{bean.method}" ... />In these cases, the method returns void. So by default, the page submits to itself. The URL does not change.
Friday, July 13, 2012
Servet, JSF, Weblogic Standards Compliance
The current version of JSF is 2. I think JSF is a layer on top of servlet. So between JSF and the application server, the common ground is the servlet version used. According to this link "http://javaserverfaces.java.net/presentations/20090520-jsf2-datasheet.pdf", JSF 2.0 is compatible with JavaEE 5 application servers, or any server implementing Servlet 2.5. For weblogic 10.3, it has a list of supported standards. From the link "http://docs.oracle.com/cd/E12840_01/wls/docs103/notes/new.html", it supports Java EE version 5.0 and Java EE servlet version 2.5, 2.4, 2.3, and 2.2. So here the common ground is servlet version 2.5, and it should be OK to use JSF 2 in weblogic 10.3.
The following information from wikipedia http://en.wikipedia.org/wiki/Oracle_WebLogic_Server is also helpful.
The table below lists major standards supported by WebLogic Server product version.
| Standard | WLS 7.0 | WLS 8.1 | WLS 9.0 | WLS 10.0 | WLS 10.3 | WLS 12c |
|---|---|---|---|---|---|---|
| Java | 1.3 | 1.4 | 5 | 5 | 6 (7 in 10.3.6+) | 7 |
| Java EE | 1.3 | 1.3 | 1.4 | 5 | 5 | 6 |
| Servlet | 1.2 | 2.3 | 2.4 | 2.5 | 2.5 | 3.0 |
| JSP | 1.2 | 1.2 | 2.0 | 2.1 | 2.1 | 2.2 |
| EJB | 2.0 | 2.0 | 2.1 | 3.0 | 3.0 | 3.1 |
| JDBC | 2.0 | 2.0 | 3.0 | 3.0 | 3.0 | 4.0 |
Thursday, June 14, 2012
The Different Ways To Specify the Converter and the Validator In JSF
The Customer Converter
The Customer Converter Without Parameters
In the following, we use the conventional prefix "f" and "h" for the JSF core and html tag libraries respectively. We also assume that there is a customer converter with the ID com.sample.customer.converter.id and the class name com.sample.CustomerConverter. Furthermore, we assume that this converter is used to do the conversion between a string and the object of the class com.sample.CustomerObject.Method 1
Use the converter ID. The converter ID is declared in the faces-config.xml file.
<h:inputText value="#{someBean.someVar}">
<f:converter converterId="com.sample.customer.converter.id"/>
</h:inputText>
Method 2
Use the converter attribute:
<h:inputText value="#{someBean.someVar}" converter="com.sample.customer.converter.id" />
Method 3
Implements a method in the back bean to return a converter:
<h:inputText value="#{someBean.somevar}" converter="#{backBean.converter}" />
Here the backBean class must implement the following method:
public Converter getConverter(){...}
Method 4
If the converter class CustomerConverter is used for all the conversions between the String and the object of the class CustomerObject, you can specify CustomerConverter as the default for the CustomerOjbect class in faces-config.xml. And that is it. No other things in JSP pages are needed.In faces-config.xml, do the following:
<converter>
<converter-for-class>com.sample.CustomerObject</converter-for-class>
<converter-class>com.sample.CustomerConverter</converter-class>
</converter>
In the JSP file, you simply write
<h:inputText value="#{someBean.someVar}" />
Note that here the type of the variable someVar must be the class CustomerObject.
The Customer Converter With Parameters
In this case, you will need to implement the converter class and the tag handler class for the converter. The tag handler class should extend the JSF class ConverterELTag. It should have the method createConverter() that returns an instance of the converter class. You also need to create the customer TLD file for your tag classes.Note that there is also a way so you can have a customer converter that needs parameters but you do not need to create the tag handler class and TLD files. You can just as simply use the methods described in the section "The Customer Converter Without Parameters". The trick is to pass the parameter to the back bean and get the value of that parameter from the bean when the customer converter does the conversion. The following is an example.
<h:outputText value="#{someBean.someVar}">
<f:converter converterId="myConverterId" />
<f:attribute name="myConverterParameterName" value="someValue" />
</h:outputText>
Then in the converter, you can get the parameter value as follows:
parameterValue = component.getAttributes().get("myCoverterParameterName");
The Customer Validator
The Customer Validator Without Parameters
Mehtod 1
<h:inputText .... >
<f:validator validatorId="..." />
</h:inputText>
Method 2
<h:inputText value="#{someBean.someVar}" validator="#{someBean.validatingMethod}" />
Notice here that the method in the "validator" attribute does not return an object of the validator class. Instead, its return type is void. This is different from the converter case where the corresponding method returns an object of the customer converter class. Here the validation method validates the data and throws a ValidatorException( a Runtime exception ) if it finds any error.
The Customer Validator With Parameters
In this case, you will need to implement the validator class and the tag handler class for the validator. The tag handler class should extend the JSF class ValidatorELTag. It should have the method createValidator() that returns an instance of the validator class. You also need to create the customer TLD file for your tag classes.References
1. Core JavaServer Faces by David Geary and Cay HorstmannHow to Specify Source Code When Debugging in Eclipse
- In eclipse, go to "Run --> Debug configurations...". This will open the configuration screen.
- In the screen, the left pane shows a list of the programs. Click on the one you are using. In this example, it is "Oracle Weblogic Server 11gR1 PatchSet 1 at localhost".The right pane will show tabs named "Server", "Source", "Environment", etc.
- In that right pane, click on the "Source" tab. You will see a list of the projects and files. These are the source code files that eclipse uses to show in debugging.
- In that right pane, you can use the "Add" button to add source code file. You can also have different versions of the source code for a library. In that case, you can use the "Up" and "Down" button to move the positions of the source code file. The one sitting higher will be picked up.
Wednesday, June 13, 2012
JSF and JSP Architecture Models
The Model 1 Architecture
In this model, the target of every request is a JSP page. The JSP page does all the things to answer the request. It can use JavaBeans to access database or other services.The Model 2 Architecture
This model follows the Model-View-Controller(MVC) design pattern. In this architecture, all the requests are received by the servlets first. The servlets act as the controller. They analyze the request, get the data into JavaBeans, and finally dispatch the requests to JSP pages. The JavaBeans act as the model. And the JSP pages act as the view.What about JSF?
We know every JSP page is actually a servet. It will be compiled to a servlet class by the web container. Now in the JSF world, with all those JSF lifecyle phases, is it still following the Model 2 architecture? The answer is still "Yes" because the JSP file gives the layout and appearance of the page. But unlike the old jsp/servlet technology where the JSP writes out all the HTML text, in JSF, the servlet generated from the JSP page only produces some simple HTML text such as the header("Content-type", "text/html"). Mostly it just processes the tags and creates the object tree into the Context which are used to build the JSF component tree. Later on the faces servlet gets the component tree from the context and spits out the actual HTML text in the renderers of the components in the component tree.Roughly speaking, in the traditional Model 2, the servlet does not do much. basically it just dispatches the requests to the JSP pages and its job is done. But in JSF, the servlet will execute the JSF life cycle for every request. At some point in the life cycle, the servlet will dispatch the request to the JSP. The JSP will do its job and save the the work into the conetxt. Then the execution will return to the servlet for the life cycle to finish.
The following is one actual stacktrace from a sample JSF application. It shows an error. But that is not the interest here. From the stacktrace, we can see how the whole thing works together. We can see the following:
- The faces servlet acts as the controller. The JSF lifecyle is executed in the controller.
- The splitting line in the stacktrace is the one containing the following: com.sun.faces.context.ExternalContextImpl.dispatch. This is where the faces servlet dispatches the request to the JSP page.
- After the faces servlet dispatches the request, the servlet generated by the JSP will take over the task. In the example, it is jsp_servlet.__index.class which is generated from the JSP page index.jsp. It is missing in this case. So an error occurs.
- The jsp_servlet processes the tags in the JSP page, creates the corresponding objects from the tags and stores them into the pageContext. The jsp_servlet does not write out the actual HTML text from the tags.
- Later on in the JSF lifecycle, the JSF renderers will write out the actual HTML text that will be sent to the browser. And these occurs in the faces servlet.
javax.servlet.ServletException: [HTTP:101249][ServletContext@11930454[app:spinner module:spinner path:/spinner spec-version:2.5]]: Servlet class jsp_servlet.__index for servlet /index.jsp could not be loaded because the requested class was not found in the classpath . java.lang.ClassNotFoundException: jsp_servlet.__index. at weblogic.servlet.internal.ServletStubImpl.prepareServlet(ServletStubImpl.java:543) at weblogic.servlet.jsp.JspStub.prepareServlet(JspStub.java:271) at weblogic.servlet.jsp.JspStub.prepareServlet(JspStub.java:191) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:235) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175) at weblogic.servlet.internal.RequestDispatcherImpl.invokeServlet(RequestDispatcherImpl.java:502) at weblogic.servlet.internal.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:248) at com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:410) at com.sun.faces.application.ViewHandlerImpl.executePageToBuildView(ViewHandlerImpl.java:469) at com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:140) at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110) at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100) at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:245) at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227) at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292) at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3592) at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321) at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121) at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2202) at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2108) at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1432) at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201) at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)In the correct version for the example above, the class jsp_servlet._index.class is at the right location. Looking at the actual code, you can see the majority of the class is the methods of the following type:
private boolean _jsp__tagX(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response, javax.servlet.jsp.PageContext pageContext, javax.servlet.jsp.tagext.JspTag activeTag, com.sun.faces.taglib.html_basic.PanelGridTag parent) throws java.lang.Throwable
{
The method name is _jsp__tagX, where 'X' is a number. For this particular example, there are 12 such methods. X is from 0 to 11, each corresponding to an actual tag in the JSP file.
A main method in _index.java is the following:
public final class __index extends weblogic.servlet.jsp.JspBase implements weblogic.servlet.jsp.StaleIndicator {
...
public void _jspService(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException {
javax.servlet.ServletConfig config = getServletConfig();
javax.servlet.ServletContext application = config.getServletContext();
javax.servlet.jsp.tagext.JspTag _activeTag = null;
java.lang.Object page = this;
javax.servlet.jsp.PageContext pageContext = javax.servlet.jsp.JspFactory.getDefaultFactory().getPageContext(this, request, response, null, true , 8192 , true );
response.setHeader("Content-Type", "text/html");
javax.servlet.jsp.JspWriter out = pageContext.getOut();
weblogic.servlet.jsp.ByteWriter bw = (weblogic.servlet.jsp.ByteWriter)out;
bw.setInitCharacterEncoding(_WL_ORIGINAL_ENCODING, _WL_ENCODED_BYTES_OK);
javax.servlet.jsp.JspWriter _originalOut = out;
javax.servlet.http.HttpSession session = request.getSession( true );
try {;
bw.write(_wl_block0Bytes, _wl_block0);
bw.write(_wl_block1Bytes, _wl_block1);
bw.write(_wl_block1Bytes, _wl_block1);
bw.write(_wl_block1Bytes, _wl_block1);
if (_jsp__tag0(request, response, pageContext, _activeTag, null))
return;
bw.write(_wl_block9Bytes, _wl_block9);
} catch (java.lang.Throwable __ee){
if(!(__ee instanceof javax.servlet.jsp.SkipPageException)) {
while ((out != null) && (out != _originalOut)) out = pageContext.popBody();
_releaseTags(pageContext, _activeTag);
pageContext.handlePageException(__ee);
}
}
}
....
}
The method above calls _jsp_tag0() which will in turn calls _jsp_tag1(), .... The mehtod _jsp_tag0 is for the ViewTag. The method is as follows:
private boolean _jsp__tag0(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response, javax.servlet.jsp.PageContext pageContext, javax.servlet.jsp.tagext.JspTag activeTag, javax.servlet.jsp.tagext.JspTag parent) throws java.lang.Throwable
{
javax.servlet.jsp.tagext.JspTag _activeTag = activeTag;
javax.servlet.jsp.JspWriter out = pageContext.getOut();
weblogic.servlet.jsp.ByteWriter bw = (weblogic.servlet.jsp.ByteWriter) out;
com.sun.faces.taglib.jsf_core.ViewTag __tag0 = null ;
int __result__tag0 = 0 ;
if (__tag0 == null ){
__tag0 = new com.sun.faces.taglib.jsf_core.ViewTag ();
weblogic.servlet.jsp.DependencyInjectionHelper.inject(pageContext, __tag0);
}
__tag0.setPageContext(pageContext);
__tag0.setParent(null);
__tag0.setJspId("id0");
_activeTag=__tag0;
__result__tag0 = __tag0.doStartTag();
if (__result__tag0!= javax.servlet.jsp.tagext.Tag.SKIP_BODY){
try {
if (__result__tag0== javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_BUFFERED) {
out = pageContext.pushBody();
bw = (weblogic.servlet.jsp.ByteWriter)out;
__tag0.setBodyContent(( javax.servlet.jsp.tagext.BodyContent)out);
__tag0.doInitBody();
}
do {
bw.write(_wl_block2Bytes, _wl_block2);
if (_jsp__tag1(request, response, pageContext, _activeTag, __tag0))
return true;
bw.write(_wl_block3Bytes, _wl_block3);
if (_jsp__tag2(request, response, pageContext, _activeTag, __tag0))
return true;
bw.write(_wl_block8Bytes, _wl_block8);
} while (__tag0.doAfterBody()== javax.servlet.jsp.tagext.IterationTag.EVAL_BODY_AGAIN);
} finally {
if (__result__tag0== javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_BUFFERED) {
out = pageContext.popBody();
bw = (weblogic.servlet.jsp.ByteWriter)out;
}
}
}
if (__tag0.doEndTag()== javax.servlet.jsp.tagext.Tag.SKIP_PAGE){
_activeTag = null;
_releaseTags(pageContext, __tag0);
return true;
}
_activeTag=__tag0.getParent();
weblogic.servlet.jsp.DependencyInjectionHelper.preDestroy(pageContext, __tag0);
__tag0.release();
return false;
}
Notice that line in red "weblogic.servlet.jsp.DependencyInjectionHelper.inject(pageContext, __tag0);". This looks like to process the tag and save the values into the pageContext. The other methods _jsp_tagX() are similar.
Understanding the Java Stack Trace
pringStackTrace
public void printStackTrace()Prints this throwable and its backtrace to the standard error stream. This method prints a stack trace for this Throwable object on the error output stream that is the value of the field System.err. The first line of output contains the result of the toString() method for this object. Remaining lines represent data previously recorded by the method fillInStackTrace(). The format of this information depends on the implementation, but the following example may be regarded as typical:
java.lang.NullPointerException
at MyClass.mash(MyClass.java:9)
at MyClass.crunch(MyClass.java:6)
at MyClass.main(MyClass.java:3)
This example was produced by running the program:
class MyClass {
public static void main(String[] args) {
crunch(null);
}
static void crunch(int[] a) {
mash(a);
}
static void mash(int[] b) {
System.out.println(b[0]);
}
}
The backtrace for a throwable with an initialized, non-null cause should generally include the backtrace for the cause. The format of this information depends on the implementation, but the following example may be regarded as typical:
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Note the presence of lines containing the characters "...". These lines indicate that the remainder of the stack trace for this exception matches the indicated number of frames from the bottom of the stack trace of the exception that was caused by this exception (the "enclosing" exception). This shorthand can greatly reduce the length of the output in the common case where a wrapped exception is thrown from same method as the "causative exception" is caught. The above example was produced by running the program:
public class Junk {
public static void main(String args[]) {
try {
a();
} catch(HighLevelException e) {
e.printStackTrace();
}
}
static void a() throws HighLevelException {
try {
b();
} catch(MidLevelException e) {
throw new HighLevelException(e);
}
}
static void b() throws MidLevelException {
c();
}
static void c() throws MidLevelException {
try {
d();
} catch(LowLevelException e) {
throw new MidLevelException(e);
}
}
static void d() throws LowLevelException {
e();
}
static void e() throws LowLevelException {
throw new LowLevelException();
}
}
class HighLevelException extends Exception {
HighLevelException(Throwable cause) { super(cause); }
}
class MidLevelException extends Exception {
MidLevelException(Throwable cause) { super(cause); }
}
class LowLevelException extends Exception {
}
But be careful about the accuracy here. The following is also from the javadoc about the method
public StackTraceElement[] getStackTrace()Provides programmatic access to the stack trace information printed by printStackTrace().
Some virtual machines may, under some circumstances, omit one or more stack frames from the stack trace. In the extreme case, a virtual machine that has no stack trace information concerning this throwable is permitted to return a zero-length array from this method. Generally speaking, the array returned by this method will contain one element for every frame that would be printed by printStackTrace.
