JSF Interview Questions and Answers: Overview
Q. If you are using JSF, what other frameworks would you require and why? A. JavaServer Faces (JSF) brings a new paradigm to developing Web-based applications in Java. However, it has a number of gaps in its out-of-the-box state. The frameworks such as Facelets and JBoss seam fill in these gaps. Facelets are an alternative view technology based on pure XML templates (no scriptlets) which was introduced with Version 2 of the JSF standard. They can only be used in a JSF application. JSPs can be used with JSF for view, but unlike JSPs, Facelets is a templating language built from the ground up with the JSF component life cycle in mind. |
With Facelets, you produce templates that build a component tree, not a servlet. This allows for greater reuse than JSPs because you can compose components out of a composition of other components. Facelets tap into the "Restore View" and "Render Response" phases of the JSF life cycle as shown below.
Seam integrates technologies such as Asynchronous JavaScript and XML (AJAX), JavaServer Faces (JSF), Java Persistence (JPA), Enterprise Java Beans (EJB 3.0) and Business Process Management (BPM) into a unified full-stack solution. Seam extends JSF with handful of annotations, extra functionality for multi-window operation and workspace management, conversational scopes to minimize HTTP session abuse, model-based validation, jBPM-based pageflow, internationalization, page fragment caching.and bookmarkable RESTful style web pages.
There are other useful optional frameworks like Tucky URL rewrite filter for RESTful URLs, JSFUnit for testing, JQuery for JavaScript, and JSF component libraries like RichFaces, ICEfaces, Trinidad, PrimeFaces, and Tomahawk for rich JSF components. But use these rich component libraries wisely as they could cause your generated HTML pages to be bloated. Bloated pages can take longer to render.
Q. In your experience, what are some of the JSF pitfalls to watch out for?
A.
1. Putting business logic or data access logic in the getter methods. Getters are solely there to access bean properties, not to do some business logic or retrieve data from a database. A getter will normally be called twice or three times per JSF request-response cycle, but it can get called more times, especially when used in UIData components. So, don't use a getter for other purposes than just returning the data.
Conditionally rendering, enabling/disabling, or making it editable or not, etc can get called many times in a data-table. For example, if the rendered attribute occurs in a single row of a data-table, then number of invocations of the backing method will be invoked by the number of rows in the table. In a table with 50 rows, it will be invoked 50 times. If it is used in 4 of the columns in each row, it will be invoked 50 * 4 = 200 times. So, it is imperative that the logic is efficient or else it will have a huge impact on performance.
2. Using too many rich components from third-party libraries like Richfaces, ICEFaces, etc could adversely impact performance due to bloated HTML pages. JSF saves two things between requests:
- the view (all the HTML controls on the page like text fields, buttons, etc)
- the view state (the state of the controls)
3. Having too many backing beans in session scope could lead to memory and performance issues. If you want to have book-markable URLs, you will need to perform redirects, and redirects will blow away the request parameters as new requests will be made. So, you must use the session scope. To prevent any potential issues due to large sessions, either provide your own implementation to periodically clear the session data or use frameworks like seam to take advantage of the conversational scope. If you use the "conversational" scope in Seam, the framework will manage the session data for you with the temporary conversation scope or you could manage it declaratively with the long-running conversational scope.
Put the components in a SEAM conversation scope, which is a slice of the HTTP session managed by the SEAM, and associated with a sequence of pages through the special token CID (i.e. Conversation ID). This conversation scope provides the developer the convenience of using the HTTP session without the memory leakage concerns, since the conversation has a much shorter lifetime and is kept isolated from other parallel conversations in the same session. The conversation scope also has other benefits of
- ensuring that the records remain managed by the persistence context while being modified.
- reducing the number of calls to the database by making previously viewed result pages to load faster since the records are already in Hibernate persistent context (i.e. first-level cache).
- maintaining the pagination details like search criteria, current page number, page offset, etc.
Following is thread-safe because a new instance will be created for every input element in view.
1
2
3
| <h:inputText ...> <f:converter converterId= "converterId" /> </h:inputWhatever> |
Following is not threadsafe because the same instance will be shared across all views of the entire application
1
| <h:inputText converter= "#{applicationBean.converter}" .... /> |
5. Not carefully designing the GUI and the relevant interactions. The JSF data centric applications involve presenting the data in a tabular format, filtering the data, paginating the data, selecting the data via check boxes, and modifying the data. It is imperative to properly think through the various interactions and properly performance test them. For example,
- Building a composite AJAX enabled component that allows partial page rendering can improve performance. This is provided by the Ajax4jsf component. Ajax4jsf provides a set of tag libraries that ties JSF generated event to the rendering of one or more regions of the user-interface identified by their JSF client IDs. When the AJAX event is sent to the server, instead of the JSF servlet returning an entire page response, it returns only fragments of the HTML to render a particular region.
- Thinking carefully about splashing rendered, editable, and disable method calls within each column and row in a data table versus having them on page level. For, example editable table versus non-editable, etc.
- Not utilizing the appropriate strategy to save the viewstate. Performance measurements have shown that plain server side state saving without serialization and compressing state comes with the best values. State saving at client side is also susceptible to security concerns as well as overhead of serialization of entire JSF tree every time. Having said that, the server side strategy will consume more memory. The numberOfViewsInSession parameter can be used to limit number of calls with back buttons inside a faces form to reduce memory consumption.123456789
<context-param>
<param-name>com.sun.faces.numberOfViewsInSession</param-name>
<param-value>3</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.numberOfLogicalViews</param-name>
<param-value>10</param-value>
</context-param>
Q. How would you go about debugging a JSF application?
A.
1. You can use a PhaseListener to trace the 6 phases of the JSF lifecycle shown in the diagram above.You can use a "dummy" PhaseListener to debug the phases to see what is happening in each phase. Here is a basic example of such a LifeCycleListener you can use to trace the phases of the JSF lifecycle. For example, to better understand how the attribute immediate=true works.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| package com.mypackage; import javax.faces. event .PhaseEvent; import javax.faces. event .PhaseId; import javax.faces. event .PhaseListener; import java.util.logging.Logger; public class LifeCycleListener implements PhaseListener { protected final Logger logger = Logger.getInstance( this .getClass()); public PhaseId getPhaseId() { return PhaseId.ANY_PHASE; } public void beforePhase(PhaseEvent event ) { logger.info( "START PHASE " + event .getPhaseId()); } public void afterPhase(PhaseEvent event ) { logger.info( "END PHASE " + event .getPhaseId()); } } |
Run your log4j in debug mode.
2. Using the FacesTrace library. FacesTrace is an open-source library aiming to enhance the tracebility of applications based on JavaServer Faces. Performance metrics and general trace information of a JSF application is collected and presented in a user-friendly format. The simplest way to use the “runtime debugging” JSF tool FacesTrace is to place the <ft:trace> tag at the end of a page. You will have to declare the tag first.
1
|
3. Configure your web.xml to run in development or debug modes. For example, if you are using Facelets with JSF, set the development mode to true.
1
2
3
4
| <context-param> <param-name>facelets.DEVELOPMENT</param-name> <param-value> true </param-value> </context-param> |
and add the following to the beginning of your facelet template file.
1
| <ui:debug hotkey= "k" /> |
If you Ctrl+Shift+k is pressed, debug window will be opened and displays the component tree and scoped variables.
If you are using Seam, set the debug mode to true.
1
2
3
4
| <context-param> <param-name>org.jboss.seam.core.init.debug</param-name> <param-value> true </param-value> </context-param> |
4. Use browsers' debugging capabilities like FireBug plugin for FireFox or Google chrome's out of the box inspect element capability to view the generated HTML source code to get some hints. FireBug for FireFox and Fiddler2 for Internet Explorer can debug AJAX calls.
Q. What is the purpose of the attribute immediate=true
A. The immediate attribute is used in UIInput and UICommand components for the following purposes :
1. Immediate attribute, when set to true, allows a UICommand component like commandLink or commandButton to process the back-end logic and ignore validation process related to the fields on the page. This allows navigation to occur even when there are validation errors.
In the code below, navigation is performed for button click without validating the required field
1
2
3
| <h:inputText id= "input1" required= "true" /> <h:message for = "input1" /> <h:commandButton value= "submit" immediate= "true" action= "send" /> |
2. To make one or more UIInput components "high priority" for validation, so validation is performed, if there is any invalid component data, only for high priority input components and not for low priority input components in the page. This helps reducing the number of error messages shown on the page.
In the code below, validation is performed only for the first component when button is clicked because the immediate=true.
1
2
3
4
5
| <h:inputText id= "input1" immediate= "true" required= "true" /> <h:inputText id= "input2" required= "true" /> <h:message for = "input1" /> <h:message for = "input2" /> <h:commandButton value= "submit" action= "send" /> |
There are a number of good tutorials and info online like The BalusC Code.
More JSF Interview Questions and Answers
- JSF Interview Questions and Answers: postback and viewstate
- JSF Interview Questions and Answers: Seam
- JSF Interview Questions and Answers: events handling
Comments
Post a Comment