Alexander Smirnov’s personal Weblog

March 25, 2011

Maven deployer plugin for Glassfish 3.1 and Jboss

Filed under: Glassfish, Uncategorized — alexsmirnov @ 4:46 pm

Plugin features

Encouraged by the Jason Lee articles about Glassfish REST API, I added support for that API to the plugin that I use to deploy my projects, and published the code to GitHub. That’s forked from the original Maven Jboss Plugin far ago, and modified to meet my needs:

  • Find module, most suitable for deployment, in the multi-module projects. For the ‘pom’ packaging, plugin checks all dependent modules and deploys artifact with this precedence: EAR, WAR, EJB, SAR. That lets to build and deploy project to the target server in the single command: mvn package deploy.
  • Jboss downloads archives for deployment from network by http protocol. Therefore, when you deploy application to remote server, it’s necessary to put the public address of developer machine in JMX call. Plugin tries to resolve public IP for remote deployment, or can get it from configuration.
  • Added workaround for Jboss 5 bug that crashes in attempt to deploy file from url with http: protocol.
  • https: protocol added, to deploy on secured console.
  • And, at the last, it also supports Glassfish REST api with same features.

Configuration:

<project>
.....
<build>
  <plugins>
    <plugin>
      <groupId>org.richfaces.cdk</groupId>
      <artifactId>maven-deployer-plugin</artifactId>
      <version>1.0.0-SNAPSHOT</version>
      <configuration>
         <!-- configuration options -->
      <configuration>
    </plugin>
  </plugins>
</build>

Define target server

By default, plugin deploys artifact using http://localhost:4848/ URL for management application.

To define another server, use these configuration options:

  • <targetHost> – hostname or IP address of target server.
  • <targetPort> – http port where management application listening, if it different from default 4848.
  • <secure> – if you use https protocol ( enabled by asadmin enable-secure-console command ).

Authentication

By default, plugin connected to the target server as user ‘admin’ with empty password what’s Glassfish default. There are several options to define user name and password:

  1. Using <server> element in Maven settings.xml. You can create that element with the same ID as target host name, or tell plugin which id to use by <serverId> option.
  2. Define them in configuration by <username> and <password> element – not recommended for remote deployment because they visible for anyone who have acces tou your project code.
  3. use command line options -Dusername=… and -Dpassword=…

Define deployment file

For the projects with packaging ‘jar’ ‘war’ ‘ear’ ‘sar’ plugin deploys the main project artifact with the same application name as artifactId. For packaging ‘pom’, it tries to find most suitable artifact in project modules:

  1. If some module has ‘ear’ packaging, use it.
  2. Otherwise, try to find ‘war’ module.
  3. if no ‘ear’ or ‘war’ modules found, try to find ‘ejb’ or ‘sar’ modules.
  4. Otherwise, use the last module with packaging ‘jar’

The plugin has ‘aggregator’ flag in its configuration that enforces Maven to build dependent modules first. Therefore, whole project can be built and deployed by the single command:

mvn package deployer:deploy-glassfish

either from the command line, IDE or on the continuous integration server. I really use it to deploy my project to Glassfish running on Amazon EC2 cloud instance. Nirvana…

If default behavior not suitable, it can be overrided by configuration or command line options:

  • <deploymentFile>, -DdeploymentFile – path to archive to be deployed.
  • <name> -Dname – application name.
  • <contextRoot>, -DcontextRoot – web application context path.
Advertisement

Testing client-side part of JSF applications with HtmlUnit

Filed under: Java, Java server faces — alexsmirnov @ 3:54 pm

There are couple tools that can be used to test generated html and client-side scripts. The most accurate tools are  these that run test in the real browser ( for example, Selenium framework ), but, in the some cases, they cannot be used – machine that runs tests has to have GUI ( rare available on continuous integration servers ), preconfigured instances of target browsers, and these tests can take too much time because you have to start new browser instance for each test to eliminate dependencies between them.

Another option is client emulator, that only simulates target browser. Although it’s less accurate then the real browser, the advantages are: no additional software required, it runs faster, and test code has full control on test client configuration. For developer tests in RichFaces, we use HtmlUnit library, integrated with our embedded FacesEnvironment.

Usage

Dependencies

HtmlUnit teste require these dependencies :
Test Project
+- org.jboss.test-jsf:jsf-test-stage
+- org.jboss.test-jsf:jsf-test-jetty ( optional )
+- org.jboss.test-jsf:htmlunit-client
+- javax.servlet:servlet-api
+- javax.servlet.jsp:jsp-api
+- javax.el:el-api
+- javax.servlet:jstl
+- junit:junit
+- com.sun.faces:jsf-api
\- com.sun.faces:jsf-impl ( or any other you want to test with ).
htmlunit-client does not contain dependencies for servlet or JSF because it can be used with different versions and implementations.

HtmlUnitEnvironment

HtmlUnitEnvironment combines embedded JSF environment and HtmlUnit client designed to work with it. Test example:
public class FacesTest {
 private HtmlUnitEnvironment environment;
 @Before
 public void setUp() throws Exception {
 this.environment = new HtmlUnitEnvironment();
 this.environment.withWebRoot("org/jboss/test/hello.xhtml").start();
 }
 @After
 public void tearDown() throws Exception {
 this.environment.release();
 }
In this test, the new instance of HtmlUnitEnvironment created  before each test, configured with virtual web application from package ‘org/jboss/test’ content and initialized to serve requests. The tearDown() method stops environment after each test and releases its resources.

Using in tests

The simple test gets JSF page, fills input field with new value and submits form to server.
After submit, it verifies that input element set new value to the session-scope bean ant that value was rendered back by outputText component:
@Test
 public void testHelloFacelets() throws Exception {
 HtmlPage page = environment.getPage("/hello.jsf");
 HtmlForm htmlForm = page.getFormByName("helloForm");
 HtmlInput input = htmlForm.getInputByName("helloForm:username");
 input.setValueAttribute("foo");
 HtmlElement submitElement = page.getElementById("helloForm:submit");
 HtmlPage responsePage = submitElement.click();
 HttpSession session = environment.getServer().getSession(false);
 HelloBean bean = (HelloBean) session.getAttribute("HelloBean");
 assertEquals("foo", bean.getName());
 Element span = responsePage.getElementById("responseform:userLabel");
 assertEquals("foo", span.getTextContent().trim());
 }

HtmlUnitRule

In Junit 4.x, MethodRule version of environment can be used instead of setup/release it in code. This example does the same as one with @Before/@After methods:
public class FacesTest {
 @Rule
 public HtmlUnitRule environment= HtmlUnitRule.create().withWebRoot("org/jboss/test/hello.xhtml");

March 24, 2011

RichFaces JavaScript service

Filed under: Java, Java server faces — alexsmirnov @ 3:22 pm

Preface

In the modern Web interface development, inline event handlers considered as the bad practice – see article for detail.
Also, for performance reason, Web experts ( Yahoo  YSlow, Google  Page Speed and others ) recomend to load  plain html code first, and only add user interaction code at the bottom of page.
For the same reason, all JavaScript files has better to be loaded at the bottom of page too.
jQuery library makes that stile pretty easy, using $(page).ready() or just $() callbacks. But, there is a problem with JSF AJAX: jQuery knows nothing about JSF library, and code inside page.ready handler will nether be called after page update.
Another drawback for JavaScript dependencies comes from the JSF 2 component resources which cannot be changed from per-component dependencies ( useful for development stage ) to solid compact library or external CDN refferences.
RichFaces JavaScript service designed to solve problems above.

How it works

RichFaces provides JavaScriptService object ( available via ServiceTracker )  to render JavaScript defeered JavaScript code at the bottom of the page or inside jQuery page.ready handler.
Getting service instance:
JavaScriptService javaScriptService = ServiceTracker.getService(JavaScriptService.class);

The service instance created by RichFaces initialization listener, and can be replaced by different implementation by custom Module, see documentation for ServiceTracker.
Adding script to be rendered at the bottom of page:
javaScriptService.addScript(facesContext, script);

What does this method do ? It looking for special UIScripts component in the UIViewRoot.componentResources collection, or creates new if there to such component yet, and append script object to the Set of objects submitted to be rendered. To avoid rendering of the same script more then once, it checks collection for the same script ( using equals() method ). If the same object already submitted to be rendered, it returns existing object. Otherwise, new script added to the collection and returned by method. That check allows to render the same script only once, even if component that requires such code rendered many times.
For example, component that wraps jQuery widget can use special ‘class’ attribute to mark its instance on the page, and the same script can activate all widgets using that class as discriminator.
Another method lets developer to append script that will be rendered inside page.ready handler:
javaScriptService.addPageReadyScript(facesContext, script);

The only difference with addScript() method that scripts appended into separate collection that processed in the special way. UIScript component writes them inside such JavaScript code:
<script type=”text/javascript>

$(document).ready(function() {

content of the scripts collection goes here

});

</script>

See jQuery documentation for ready() function for details how it works.
For AJAX requests ( important note – only RichFaces AjaxBehavior supported ) the same scripts rendered in the <execute> part of response that processed after DOM updates. Therefore, the same code works for both page rendering and AJAX modes.
In addition, script object can implement org.richfaces.resource.ResourceLibrary interface and provide additional dependencies. These dependencies will be rendered as links to external resources before in-content <script> element.

 

Test JSF applications with staging server.

Filed under: Java, Java server faces — alexsmirnov @ 3:18 pm

Test JSF Applications with Embedded Server

Preface

JSF is very complicated framework, with a lot of tight related components, that makes testing pretty complicated. It runs inside Servlet container, and framework behavior depends from container configuration. The goal of embedded servlet container is providing flexible test environment suitable to test parts of JSF application: Composite components, view fragments and templates. The idea is very similar to Jboss Arquilian framework, with some JSF-specific extensions. The main answer to the question why to not use Arquillian to test RichFaces components is what it was introduced far before  Jboss implementation. Another answer is JSF-specific features and speed, embedded stage server runs much faster real implementations.

Features

  • Container runs in the same thread that performs client request, what allows test code to inspect request-scope objects, or even interrupt request processing for asserts.
  • Container configuration made from the java code, that lets every test has its own settings and web application content. For example, the same test can be invoked with different initialization parameters.
  • Extremely fast, container doesn’t parese any configuration files, setup network connections or instantiate multiply applications.
  • Single Java object holds container instance, therefore it can be used with any test framework.
  • Integration with HtmlUnit to simulate web client.

Limitations

  • No JSP compiler, only Facelets views can be used.
  • Ignores web.xml content. Container should be configured from Java code.
  • No network access
  • No JNDI, no injection, only base javax.servlet interfaces.
  • No transactions
  • By default, FacesServlet initialized with suffix-based mapping ‘*.jsf’.

Usage

Instantiation of FacesEnvironment

jUnit 4 test class fragment:
private FacesEnvironment environment;
@Before
public void setUp() {
environment = FacesEnvironment.createEnvironment().start();
}
@After
public void thearDown() throws Exception{
environment.release();
}
This code creates an instance of environment, initializes JSF framework and starts server instance before each test, and releases resources after test. The version of this method with ApplicationServer parameter lets create environment for different server implementation ( currently, embedded Jetty server supported ).

Configuration

FacesEnvironment class has set of configuration methods to describe web application context and setup server. all methods returns back the same instance, so they can be chained:
withContent(String,String) – define content of web resource for given path:
environment = FacesEnvironment.createEnvironment().withContent(“/test.xhtml”,
“<html xmlns=\”http://www.w3.org/1999/xhtml\”\n” +
”      xmlns:ui=\”http://java.sun.com/jsf/facelets\”\n” +
”      xmlns:h=\”http://java.sun.com/jsf/html\”>”+
“<h:form id=\”helloForm\” >”+
”    <h:outputText value=\”foo_bar\” />\n” +
“</h:form>\n” +
“</html>”).start();
withResource(String,String) – put content of classpath resource to the given path in servlet context.
withWebRoot(String) – create virtual web server context from the package containing given resource. Suitable to create web application fragment from resources stored in the jar. Another way to create vitrual servlet context is system property ‘webroot’, that should contain path to the folder with web application content.
withResourcesFromDirectory(String path, URL resource) – Add all resources from the directory to the virtual web application content. Only ‘file’ or ‘jar’ protocols are supported. If this parameter points to a file, it will be converted to a enclosing directory.
withInitParameter(String name, String value) – add ServletContext initialization parameter to value.
withFilter(String name, Filter filter) – add filter in front of FacesServlet.
Additional configuration can be performed directly on the ApplicationServer instance, see JavaDoc for details.

Performing request

To perform JSF request, call environment.createFacesRequest(String url) method:
@Test
public void testRequest() throws Exception {
FacesRequest request = environment.createFacesRequest(“http://localhost/test.jsf&#8221;);
assertNotNull(request.execute());
String contentAsString = request.getConnection().getContentAsString();
assertTrue(contentAsString.contains(ResponseStateManager.VIEW_STATE_PARAM));
}
This method gets request URL and returns FacesRequest object, that allows additional configuration ( adding request parameters, cookies, headers ). The request is not active until start() or execute() methods callled. execute() method performs whole request cycle, while start() only initialized request, created FacesContext and returns, that allows test to execute Faces Lifecycle directly inside request context.

FacesRule

FacesRule is jUnit 4 MethodRule that invoked around every test method. It automatically configures and starts converter before method and shut down it after. Using method rule allows to combine with another rules ot test runners – jsf-test MockRunner, Mockito runner, parametrised tests. There is fragment of test that creates mock instances of Jsf beans and run facelets fragment with user registration form, using mock objects for  ‘facade’ and ‘user’ beans:
@RunWith(MockitoJUnitRunner.class)
public class RegisterTest implements ServletRequestListener{

@Rule
public FacesRule rule = HtmlUnitRule.create().withResource(“/registerTest.xhtml”, “registerTest.xhtml”).withListener(this);
@Mock
Facade facade;
@Mock
User user;
@Before
public void setUp() throws Exception {
rule.setSessionAttribute(“facade”, facade);
}
public void requestInitialized(ServletRequestEvent sre) {
sre.getServletRequest().setAttribute(“user”, user);
}

registerTest.xhtml only includes registration form fragment by <ui:include> directive. Therefore, this test lets check functionality of the single fragment without having real EJB for facade, database, and without inference from other parts of application.

March 23, 2011

JSF Mocks

Filed under: Java, Java server faces — alexsmirnov @ 4:23 pm

Preface

In the Test Driven Development mocking real objects is one of fundamental parts. For low-level JSF components and extensions development, having mocking framework environment is necessary for unit testing. Unfortunately, there are some problems:

  1. Most classes from JSF API not interfaces, but abstract and concrete classes. While modern mocking libraries, Mockito, jsf class extensions, and others, allows to mock concrete classes, all of them require some bytecode manipulation library to create mocks at runtime. For example, both Jboss Seam and EasyMock class extensions require different versions of javaassist library.
  2. Libraries like Apache Shale provide stub objects for JSF api, that not so convenient for testing, and none of them had JSF 2.0 version at the Richfaces 4.0 development time.

The idea behind jsf-mock project was similar to Easymock class extension library ( create subclasses for mocked objects that delegate calls to the EasyMock  environment ), but, because we know which classes from JSF API should be wrapped, do it at compilation time and provide ready to use mock objects for tests.

Target environment

Jsf-mock objects can be used with:

  1. both Jsf 1.2 and 2.x, depends only from the jsf-api library used for tests.
  2. EasyMock 2.5.2 and late.
  3. Junit 3.x and 4.x, while we recommend to use Junit 4.8 and later for which we provide runners and method rules that takes care most of configuration jobs.
  4. TestNG.

Mock Generator Maven Plugin

All mock classes generated by the maven-mock-generator-plugin. This plugin intended for internal use to generate jsf-mock library, but can be also used to create mocks for custom JSF components. That plugin generates mock classes for all JSF objects and utility class that instantiates these objects.

Usage.

The simplest way to create mock objects for JSF is using FacesMock#createMock(Class toMock) method, or similar other from the FacesMock class. These methods have the same signatures and functionality as in the EasyMock class, but, if the class to mock beyond JSF API, it creates an instance of precompiled mock class. Otherwise, call will be delegated to corresponded EasyMock class.

There are some problem with JSF. Sometimes, it may be necessary to use FactoryFinder#findFactory or FacesConstect#getCurrentInstance static methods, that cannot be mocked.

FacesEnvironment

To solve that problem, jsf-mock project contains MockFacesEnvironment class that performs necessary configuration procedures. That class designed to use as internal field in the test class, and can be used with any test framework: Junit 3 and 4, or Testng.

Usage, with Junit 4.8:

private MockFacesEnvironment mockEnvironment;

 

@Before

public void setUp() throws Exception {

this.mockEnvironment = FacesMock.createMockEnvironment();

}

 

@After

public void tearDown() throws Exception {

// Necessary to clean up ThreadLocal variable in FacesContext.

mockEnvironment.release();

}

MockFacesEnvironment has a set of configuration methods ( having ‘with’ prefix ) that can be chained to describe requested features:

mockEnvironment.withServletRequest().withRenderKit();

Also, it contains the same set of create…Mock methods as FacesMock class. All mock objects created by environment can be resetted/replayed/verified by single call to environment instance.

Advanced usage, with Junit 4.x

Junit 4 introduced TestRunner feature that allows developer define its own extentions for test environment. Jsf-mock contains MockTestRunner class that simplifies working with mock objects:

  1. For fields in the test class and its superclasses, annotated by @Mock, @Strict, or @Stub annotations, it creates and injects ready to use mock object.
  2. It creates and initializes MockFacesEnvironment object, and injects it into field annotated with @Environment. Developer can describe requested environment features by annotation options. After a test, runner properly releases the environment.
  3. if field with type MockController exists in the test class, it injects controller instance there. That controller can be used to reset/replay/verify all mock objects created by the runner in the single method.

Mocking JSF view

Sometimes, it would be necessary to create not just mock component but fragment of JSF view. For example, to test UIData renderer, table component should contain columne and headers/footers. There is ViewBuilder class to do that:

ViewBuilder viewBuilder = ViewBuilder.createView().children(

ViewBuilder.component().id(“foo”),

ViewBuilder.component(UIInput.class).id(“input”)

).facets(

ViewBuilder.facet(“header”)

).setViewId(FOO_XML);

viewBuilder.replay();

Capturing ResponseWriter output

For custom renderers, it would be important to check generated html code. Faces-mocks allows developers to capture renderer output and analyse it with XPath-like criteria:

writer = new RecordingResponseWriter(“UTF-8″,”text/html”);

… call renderer to generate content

// verify output

assertEquals(“id1”,writer.find().element(“.*”).withAttribute(“id”).getAttribute(“id”));

 

MockFacesEnvironment creates capturing response writer if it requested by withResponseWriter() call, or Feature.RESPONSE_WRITER option in @Environment annotation.

Maven artifact for jsf-mock project available from Jboss Maven Repository, the source code repository on GitHub is git://github.com/alexsmirnov/jsf-test.git

Create a free website or blog at WordPress.com.