Tuesday, May 19, 2009
Fast Esp : QRServer and fdispatch not connected
Resolution:
Restart the fdispatch and QRServer processes and then complete the following general debugging procedure:
1. Turn on fnet debugging:
http://:15100/control?debug.fnet=1
2. Issue some queries.
2. Look at the output in qrserver.scrap for output similar to the following:
[2004-01-21 09:33:07] INFO : qrserver->fnet: events[/s][loop/int/io][
967.3/0.0/1.0] packets[/s][r/w][1.0/1.0] data[kB/s][r/w][0.03/0.01]
If you find a packets[/s][r/w][0.0/1.0] message displayed, then the problem
is most likely present on your system (zero packets read per second).
4. Debug logging for RTS and searchctrl. To investigate this further, it is useful to have debug logs from two components. On all search nodes:
etc/searchrc-1.xml
set debuglog="true"
On the configuration server node:
etc/config_data/RTSearch/webcluster/rtsearchrc.xml
set debugLog="true"
5. Edit %FASTSEARCH%/etc/searchrc-dispatch.xml on search nodes with topfdispatch.
set debuglog="true"
By default the option is set to false.
6. Edit the files above accordingly. Shut down the system and restart after verifying that all the processes have terminated successfully (frtsobj.exe, fsearchctrl.exe).
FAST ESP : QRServer timed out
Error:
The exception is: no.fast.ds.search.SearchEngineException: Timed out while waiting for query result.
Resolution:
To resolve this issue, increase the source.xml, fdispatch.addon and fsearch.addon timeout values in the system.
1. Update FASTSEARCH/etc/fdispatch.addon with the following values:
maxdocsumwait = 80
maxsearchwait = 70
maxsocksilent = 120
2. Update FASTSEARCH/etc/fsearch.addon with the following value:
maxsocksilent = 120
3. Update FASTSEARCH/etc/qrserver/sources.xml with the following value:
timeout query="60" docsum="70" (the timeout tag)
4. Restart rtsearch/qrserver.
Handling Query Errors (Java Search API)
Example:
try {
IQueryResult result = engine.(query);
...
...
} catch (SearchEngineException e) {
System.err.println("Error " + e.getMessage() + ": " + e.getErrorCode());
}
A nonzero error code indicates query related error messages.
FAST ESP Adminserver error codes and messages
Severity:
ERROR
Log message
com.fastsearch.esp.admin.
engine.corba.JacORBNameserviceService
[Nameservice@null:0 Local@null:
/] could not activate ORB
(org.jacorb.orb.ORB@
) : org.omg.CORBA.
INITIALIZE: Could not create server socket
vmcid: 0x0 minor code: 0 completed: No
Cause(s) :
The TCP port that Adminserver's ORB tries to bind to is unavailable.
This is most likely due to another instance of Adminserver running or not properly shut down.
Action(s):
Check if Adminserver is already running. If it is, terminate it and restart Adminserver. Check if some other process has bound to either of the two TCP ports with 'netstat -an'. Make sure no other processes are running in the FAST ESP port range before starting FAST ESP.
FAST ESP Error Messages
XML template:
Text template:
#SEG NAM _SEGNAME_
####
#ERC 1102
#ERT Could not open channel to server.
####
Note:
Error messages in the 10xx range originate from the Search Engine.
Error messages above that originate from the Query & Result Server.
Code Description :
1001 General error. Unexpected internal error message. Contact FAST Technical Support.
1002 Error parsing query. Check the query syntax. Note: When using the FQL query language a query syntax error is normally reported by error message 1201
1003 All partitions are down (Search Engine). Verify installation (System Management) and network interfaces.
1004 No such dataset. A query parameter `dataset' exists but is not supported in this version of the product. Contact FAST Technical Support if this error message appears.
1005 System is overloaded. This will happen when queries are refused due to QPS license limitations.
1006 The requested functionality is not implemented. Check the query syntax and query parameters.
1007 Query not allowed to run (due to internal resource problem). Normally a temporary resource problem - Resubmit query.
1008 Lost connection to one or more Search Engine sub-nodes. Verify installation (System Management) and network interfaces. The search client should normally resubmit the query, refer to Errors related to evaluation of complex queries.
1009 Multiple errors occurred from different search partitions. The search client should normally resubmit the query, refer to section Errors related to evaluation of complex queries.
1010 Query evaluation error (Internal Search Engine error conditions). Contact FAST Technical Support.
1011 Query timeout: One or more Search Engine nodes did not respond within the query timeout limit. The search client should normally resubmit the query, refer to Errors related to evaluation of complex queries.
1012 Not enough resources, query not possible to resolve. Analyze the query that caused the error message. Refer to Errors related to evaluation of complex queries.
1013 Not enough resources, temporary problem within the Search Engine. Search Front End may re-submit. Refer to Errors related to evaluation of complex queries if the error condition always or frequently occurs for specific types of queries.
1014 Not supported - for queries that are not supported. Check query syntax. Contact FAST Technical Support if you are not able to detect errors in the query syntax.
1015 License checkout problem
1016 Requested generation no longer available. A version of the index can no longer be reached. Contact FAST Technical Support.
1020 Document summary internal error. May be a temporary resource problem, Search Front End may try to resubmit query.
1021 Document summary internal error. May also be related to a connectivity problem or search nodes out of operation. Verify installation (System Management) and network interfaces.
1022 Document summary internal error. May also be related to a connectivity problem or search nodes out of operation. Verify installation (System Management) and network interfaces.
1101 No query state supplied, nothing to search for. Contact FAST Technical Support.
1102 Could not open channel to server (No connection to search dispatcher). Verify installation (System Management) and network interfaces.
1103 No query in the query state. Contact FAST Technical Support.
1104 Failed to send query packet. Verify installation (System Management) and network interfaces.
1105 Search timed out. The search client should normally resubmit the query, refer to Errors related to evaluation of complex queries.
1106 Unknown response for query. Contact FAST Technical Support, please include information from query log.
1107 Connection failed while searching (Connection to search dispatcher failed in the query-phase. Verify installation (System Management) and network interfaces.
1108 Failed to send docsum request packet. Verify installation (System Management) and network interfaces.
1109 Docsum fetching timed out (Timed out waiting for docsums from search engine). Refer to Errors related to evaluation of complex queries.
1110 Connection failed while fetching docsums. Verify installation (System Management) and network interfaces.
1111 Unknown response while fetching docsums. Contact FAST Technical Support, please include information from query log.
1112 Failed to store hit information. Contact FAST Technical Support.
1113 Failed to allocate memory for query. Contact FAST Technical Support.
1114 Partial Result. Not possible to retrieve results from all columns (partitions). This may be caused by a connectivity error or an error with a specific search partition. Verify installation (System Management), network interfaces and the status for the search partitions.
1201 FAST Query Language (FQL) query parsing error. Refer to the error text for error details.
1202 Result processor failure. Check query parameters.
1998 Requesting a result template that is not supported. May occur when using customized result template formats.
1999 Query & Result Server error. Contact FAST Technical Support.
2000 Failed to write data to client. (Will only be present in the query logs.) This error is caused by the client closing the connection prematurely.
Wednesday, May 13, 2009
Weblogic 10 Server Compatibility
BEA attempts to support binary and source-level compatibility between the current version of WebLogic Server and all versions as far back as 8.1 in the areas of persistent data, generated classes, and API compatibility. In some cases, it is impossible to avoid incompatibilities. Where incompatibilities arise, they are fully documented in the Upgrading WebLogic Application Environments guide.
Java EE 5 Compatibility
BEA WebLogic Server 10.0 is JEE5 compatible. This compatibility allows a Java EE 5 compliant application to be developed on one operating system platform, and deployed for production on another, without requiring Java EE 5 application code changes. BEA ensures this compatibility of Java EE 5 application portability within a WebLogic Server release level.
Generated Classes Compatibility
With one exception, upgrading to WebLogic Server 10.0 does not require you to recompile applications in order to create new generated classes.
The 10.0 version of the EJBGen utility recognizes only JDK 5.0 metadata annotation-style EJBGen tags and not the old Javadoc-style tags. This means that source files that use the Javadoc-style tags must be upgraded to use the equivalent annotation, and then recompiled using the 10.0 version of EJBGen.
Compatibility Within a Domain
- All WebLogic Server instances within the same Administrative domain must be at the same major and minor version. You cannot mix server versions within a domain.
- Servers within an Administrative domain can be at different Service Pack levels as long as the Administration Server is at the same Service Pack. Level or higher than its Managed Servers.
- All servers within a cluster must be at the same Service Pack level.
JMX Compatibility
See JMX 1.2 Implementation in Upgrading WebLogic Application Environments.
Persistent Data Compatibility
Upgrading to WebLogic Server 10.0 does not require you to make any changes to WebLogic Server 8.1, 9.0, 9.1, or 9.2 persistent data storage, including configuration files, deployment descriptors, transaction logs, and JMS messages.
API Compatibility
WebLogic Server 8.1, 9.0, 9.1, and 9.2 applications deployed on WebLogic Server 9.2 will function without modification. Exceptions to this rule include cases where API behavior was changed in order to conform to a specification or to fix incorrect behavior. In certain circumstances, a correction may cause your application to behave differently.
Protocol Compatibility
Interoperability between WebLogic Server 10.0 and WebLogic Server 8.1, 9.0, 9.1 and 9.2 is supported in the following scenarios:
- A WebLogic Server 8.1, 9.0, 9.1 or 9.2 client can invoke RMI-based applications hosted on a WebLogic Server 10.0 server using IIOP, T3, T3S, HTTP, and HTTPS. JMS applications can be invoked using T3, T3S, HTTP, and HTTPS.
- A WebLogic Server 10.0 client can invoke RMI-based applications hosted on a WebLogic Server 8.1, 9.0, 9.1 or 9.2 server using IIOP, T3, T3S, HTTP, and HTTPS. JMS applications can be invoked using T3, T3S, HTTP, and HTTPS.
- A WebLogic Server 10.0 Web server plug-in can proxy to the latest service pack release of a 8.1, 9.0, 9.1 or 9.2 server.
Interoperability between WebLogic Server 7.0 and WebLogic Server 10.0 is supported in the following scenarios. You will need the WebLogic Server 7.0 patch that is associated with CR295275 for this interoperability to work. This patch is applicable to WLS 7.0 SP6 and WLS 7.0 SP7. You can request this patch by contacting BEA support and requesting the patch associated with CR295275. Additionally, for RMI/IIOP interoperability support, start the WLS 7.0 client using the following flag: -Dweblogic.system.iiop.enableClient=true
- A WebLogic Server 7.0 client can invoke RMI-based applications hosted on a WebLogic Server 10.0 server using T3, T3S, HTTP, and HTTPS. JMS applications can be invoked using T3, T3S, HTTP, and HTTPS.
- A WebLogic Server 10.0 client can invoke RMI-based applications hosted on a WebLogic Server 7.0 server using T3, T3S, HTTP, and HTTPS. JMS applications can be invoked using T3, T3S, HTTP, and HTTPS.
- A WebLogic Server 10.0 Web server plug-in can proxy to the latest service pack release of a 7.0 server.
Java PureFaces : New JSF Framework
Java PureFaces is a layer on top of JSF that simplifies implementation. The article here is the aggregate of the blog posts that I have written on our blog. The framework is not yet made public, and we are looking to see if there is interest in us releasing it as an open-source project. We are not a JSF framework company; we develop web applications. This framework is a result of our experience with the tools with which we were already working.
We are very interested in getting input from the community on it, so please let us know what you think.
Introduction
Developing the Web Tier is a big part of designing and developing a web application. Many frameworks exist that attempt to improve this part of the development. These frameworks simplify the process, providing ready tools and improving code reuse.
Most frameworks are developed around a web designer/Java developer job split, providing a simple API to the web designers, and an XML/HTML file and a Java API for the developers. Examples are Struts and JSF. Other frameworks are aimed only at Java developers and provide a Swing-like API, allowing the developers to develop a web application with only the Java language. The developer code can be very object oriented and does not need to be concerned about interacting with HTTP/ JSP/Tags etc. An example of this type of framework is GWT.
Building off of both of these, we have created a new framework for Java developers that we call Java PureFaces. This framework is built on the very popular JSF framework, but allows the web tier to be designed completely in Java -- no massive library of JSP/JSF pages or configuration files necessary.
Java PureFaces
A little over a year ago, we started looking for a way to create HTML pages without writing HTML code. It did not make sense that a developer that knows a powerful object-oriented language like Java needs to create and maintain static HTML/JSP/XML pages just because of the HTTP protocol. However, JSF is too raw to work with directly (JSF tags, value bindings, etc.).
Java PureFaces provides a pure Java framework for building the web tier. Java developers can use good object oriented solutions, increase code reuse, speed up development, and simplify code maintenance without worrying about many of the web/http concepts like HTTP, JSP, XML, Tags, HTTP sessions, etc. The API is very simple and easy to learn and use.
Like JSF, Java PureFaces binds object attributes into the GUI, and binds commands and link buttons to object methods. Also, JSF components are used to render the HTML. Unlike JSF, Pure JavaFaces attributes and commands can be bound to any POJO object, not only to a backing bean. An advantage of binding to any POJO object through Java is that the bindings themselves can be tested with JUnit.
Because the framework uses JSF, it is very extensible. In order to create a new component, we can extend the UIComponent JSF class. Also, only a single JSP page and backing bean are necessary as the container for the web application (this simplicity does mean that, like some other frameworks, you cannot refresh the page or use the browser back button).
Compare it to a standard JSF application
To quickly illustrate the simplicity of Java PureFaces, we implemented the JSF guessing number game.
Built in the Java PureFaces framework, it makes sense to create two classes: One to represent the logic and one to represent the view. These classes are:
- GuessNumber -- will know how to create a random number to guess and will check it the user number matches the guessing number.
- GuessNumberView -- is responsible to create the GUI and response to the button clicks.
Here is the code from the GuessNumberView object:
public class GuessNumberView extends EntryPage implements Serializable {
private static final long serialVersionUID = -7093024622882061259L;
private static final int minNumber = 0;
private static final int maxNumber = 10;
transient private PurePanelGroup component; //not Serializable in the session
private GuessNumber guessNumber;
public GuessNumberView() {
guessNumber = new GuessNumber(minNumber,maxNumber);
}
/**
* pressing on the submit button will create the the response component
*/
public void guessAction() {
createResponseComponent();
}
/**
* pressing on the back button will create the the guess component
*/
public void backAction() {
createGuessComponent();
}
/**
* pressing on the start button will create the the guess component and reset the number
*/
public void startAction() {
createGuessComponent();
guessNumber.start();
}
private void createGuessComponent() {
component = new PurePanelGroup();
component.setFormId("guessForm");
component.add(new PureOutput("Hi. I'm thinking of a number from " + minNumber + " to "
+ maxNumber + " Can you guess it?").setStyleClass("headerText"));
component.add(new PureInput(guessNumber, "userNumber").addValidator(new LongRangeValidator(maxNumber,
minNumber)).setIsRequired(true));
component.add(new PureErrorMessages(true, false, "list").setStyleClass("errorMessage"));
component.add(new PureButton("Submit", this, "guessAction").setStyleClass("button"));
}
private void createResponseComponent() {
component = new PurePanelGroup();
component.setFormId("guessForm");
if (guessNumber.getIsGuessCurrect()) {
component.add(new PureOutput("Yay! You got it!").setStyleClass("headerText"));
component.add(new PureButton("Start", this, "startAction").setStyleClass("button"));
} else {
component.add(new PureOutput("Sorry, " + guessNumber.getUserNumber() + "
is incorrect.").setStyleClass("headerText"));
component.add(new PureButton("Back", this, "backAction").setStyleClass("button"));
}
}
public UIComponent getRootUIComponent() {
if (component == null) {// only for the first time
createGuessComponent();
}
return component.createUIComponent();
}
public String getBackingBeanName() {
return "root";
}
}
Notice that the code to create the simple GUI, as well as the code that handles the button clicks, is cleanly packaged together. Compare this to the JSF Version.
(You can download this demo here: (RAR), (ZIP), (TGZ). There are also full demo applications on the Solutions page of our website. Both of these were created using Java PureFaces)
Clean and Simple Output
So what does the HTML from Java PureFaces look like? Before discussing exactly how the framework works, I want to show how clean it is to work with; I want to show exactly what mark-up is created. I will use a couple of examples from the previous Guess-A-Number demo to show some examples. I'll start by using a single JSP page for the project:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>Java PureFaces guessing number demo</title>
<link rel="stylesheet" href='<c:url value="/theme/demoStyle.css" />' type="text/css">
</head>
<body>
<f:view>
<h:panelGroup binding="#{root.render}"></h:panelGroup>
</f:view>
</body>
</html>
This is all that is needed in the simplest application JSP page. The #{root.render} binding is all that is needed to bind the page to the application. Here is the code of the createGuessComponent from the demo:
private void createGuessComponent() {
component = new PurePanelGroup();
component.setFormId("guessForm");
component.add(new PureOutput("Hi. I'm thinking of a number from " + minNumber + " to " +
maxNumber + " Can you guess it?").setStyleClass("headerText"));
component.add(new PureInput(guessNumber, "userNumber").addValidator(new LongRangeValidator(maxNumber,
minNumber)).setIsRequired(true));
component.add(new PureErrorMessages(true, false, "list").setStyleClass("errorMessage"));
component.add(new PureButton("Submit", this, "guessAction").setStyleClass("button"));
}
which creates this simple view:
and this clean HTML (very CSS-friendly):
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>Java PureFaces guessing number demo</title>
<link rel="stylesheet" href='/pureFaces-guessNumber/theme/demoStyle.css' type="text/css">
</head>
<body>
<form id="guessForm" name="guessForm" method="post" action="/pureFaces-guessNumber/demo.jsf"
enctype="application/x-www-form-urlencoded">
<span id="guessForm:pureFaces_root1" class="headerText">Hi. I'm thinking of a number from
0 to 10 Can you guess it?</span>
<table cellpadding="0" cellspacing="0" class="__pureFacesErrorGrid">
<tbody>
<tr>
<td><input id="guessForm:pureFaces_root2" name="guessForm:pureFaces_root2"
type="text" value="0" /></td>
<td></td>
</tr>
</tbody>
</table>
<input id="guessForm:pureFaces_root3" name="guessForm:pureFaces_root3" type="submit" value="Submit"
onclick="if(typeof window.clearFormHiddenParams_guessForm!='undefined')
{clearFormHiddenParams_guessForm('guessForm');}if(typeof window.getScrolling!='undefined')
{oamSetHiddenInput('guessForm','autoScroll',getScrolling());}" class="button" />
<input type="hidden" name="guessForm_SUBMIT" value="1" />
</body>
</html>
There is a table in there that is configured to allow for an error message next to the input box through JSF messaging. If the input field is not required, this can be removed for even simpler HTML.
This example shows that when comparing this mark-up to the Java code that created it, you can see it is almost line for line (there is no error message, so it is not rendered). You can use table-based layouts (using PurePanelGrid instead of PurePanelGroup), or work with more current semantic layouts. Either way, it is very easy to create a view. It is also very easy to manipulate the attributes of the HTML elements, like the style classes in the HTML shown here (class=). The framework model can support any element attribute, such as DOM "Level 0 Events (onclick, onkeypress, etc.) and inline styles (style=), to name a few of the more frequently used attributes, by just chaining them onto the component you are adding.
The Way It Works
Now that we have taken a look at the simplicity of the code and the HTML output, I'll describe how we detached the need for a backing bean so that any object or method can be bound to the page.
For a quick review: Typically, JSP pages are coupled with a backing bean, which contains any Java code used in the page. The backing bean must be defined in the faces-config.xml file, and is the page's interface to the rest of the system.
My point here is that:
- It is tedious to define and maintain the mapping of beans in the faces-config file, and
- The JSP page is restricted to accessing methods only in the backing bean.
The designer is forced to maintain a JSP file, an XML, and a java class -
for each page in the system (not to mention the navigation mappings, etc).
Java PureFaces removes this complexity and inflexibility. A backing bean is
required, but only one that is used to tie the whole system to a single JSP
page... and this bean is never really used after this. At least, not for binding
to the page. The objects bound to the page are part of the application. The
magic behind Java PureFaces is simple, yet extremely powerful. There is rarely
a need to touch the faces-config file or the JSP page, yet you can bind to
any method or field in the system. Here is how it works.
There are two main things that make Java Pure Faces work. The key to it is that in JSF, listeners are called before the binding.
- Command Buttons / Links: When you create a command component through the API, Java PureFaces binds that component to the single backing bean using a dummy method that simply returns "success." The work for these components is performed using ActionListeners. First the binding is tested (for testing in JUnit), and then an ActionListener is created from the parameters entered through the API.
- Inputs: All input types are set up with a default Value Change Listener directed at the desired field entered through the API. Once again, the bindings are tested first using reflection and will throw exceptions for JUnit testing.
That's all there is to it. The listeners are set up to manipulate the target of the component. It is not how JSF was meant to be used, but isn't that where some of the best uses come from? This work is all done behind the scenes, and completely removes the restrictions of the standard JSP/XML/backing bean combination. Absolutely any property can be manipulated, and any method can be triggered. This design enables the system to be completely object-oriented.
As an example to further clarify how useful Java Pure Faces can be, consider a developer who is using Hibernate and would like to bind an entity directly into a view. Using JSF, all backing beans registered in the faces-config file are instantiated at runtime by JSF. Hibernate also instantiates the entities for you. So in this case, the developer cannot do it; an entity cannot be a backing bean. There need to be extra steps to move data from the page to the entity. In Java PureFaces, this is not an issue. The JSP page binds to any POJO in the system through either a Value Change Listener or Action Listener. Hibernate instantiates the entity and anything in that entity can be bound directly into a view.
Object-Oriented API
For the final topic in this article, I want to talk about how Java PureFaces promotes object-oriented programming.
The PureComponent Interface
All Java PureFaces components implement a single interface, PureComponent, that enable them to be used in the framework. This means that, unlike some other frameworks, you do not have to extend a framework-specific object in order to have the functionality of the framwork. In a language that does not allow double-inheritence, being forced to extend another object creates inflexibility. Instead, it allows any object in the application to contain its own display code. It also allows for the creation of custom components that can be easily used throughout the system.
Component Objects
Component creation is very easy with Java PureFaces. All containers, such as PurePanelGrid and PurePanelGroup, take objects that implement PureComponent, and all components are PureComponents. To create a new custom component, you simply implement the interface and then build whatever component you need.
In this example, a simple component - that approximates an HTML label element - is created. By implementing the PureComponent interface, the object is required to implement the createUIComponent method. Inside this method, the component is created from other building blocks. The rest of the object can contain any getters and setters necessary, along with any helper methods, or really just anything at all.
This particular example makes use of another Java PureFaces convenience object called PureEditableValue. This component is a very simple object that holds a reference to a property, and contains the necessary getter and setter needed to access that property. Through the use of generics, that property can be of any type.
public class LabelAndInputComponent<E> implements PureComponent {
private String label;
private PureEditableValue<E> editableValue;
public LabelAndInputComponent(String label, E value) {
this.label = label;
this.editableValue = new PureEditableValue<E>(value);
}
public PureComponent createUIComponent() {
PurePanelGrid panelGroup = new PurePanelGrid(2);
panelGroup.setStyleClass("panelStyleClass");
panelGroup.add(new PureOutput(label).setStyleClass("lableStyleClass"));
panelGroup.add(new PureInput(editableValue).setStyleClass("inputStyleClass"));
return panelGroup;
}
public E getValue(){
return editableValue.getValue();
}
}
This component can now be used anywhere, as shown in the example below. The component is a completely object-oriented solution that can be tested through JUnit. It can extend anything it wants, and of course can implement as many interfaces as necessary. There is absolutely no restriction on making any object a Java PureFaces component.
//.. Some other view object
private LabelAndInputComponent<String> label = new LabelAndInputComponent<String>("A Label",
"default text"); // example
public PureComponent createUIComponent() {
// Create a DIV element that contains a label component
PurePanelGroup panelGroup = new PurePanelGroup();
panelGroup.setDivStyleClass("divStyleClass");
panelGroup.add(label);
return panelGroup;
}
Easier Maintenance
The final topic to cover is the ease of maintenance for a Java PureFaces implementation. For this, I will use the LabelAndInputComponent implementation that we just discussed.
Testing Java PureFaces is very easy, and very powerful. Of course, it is already easy to test the non-Java PureFaces parts of the object in JUnit the same way we would any other time. The additional advantage here is that we can test the bindings of the Java PureFaces components as well.
The way it works is that the framework tests every binding (using the Reflection API) prior to adding it to the ActionListener or ValueChangeListener. This functionality is done immediately when building the component, and an exception is thrown if something does not check out correctly. Testing the bindings is as simple as:
public void testLabelAndInputComponentImplementation() {
ThatTestObject obj = new ThatTestObject();
obj.createUIComponent();
}
This simple test creates the component and tests that all bindings are valid and able to be resolved.
And finally there is general maintenance. Everything is inside Java. The views are maintained by editing existing objects and components with the ease of whatever development environment you use. There are no JSP files to maintain, there is no XML to update. Productivity is increased by be able to work on all of the code without having to switch gears and use a separate environment. Changes are immediately available when you rebuild the project.