No results found

Your search did not match any results.

PrimeFaces in the Enterprise, Part 2: Mobile Solutions for the Enterprise

by Josh Juneau
Published October 2014

Learn how to create data-driven applications for mobile devices using PrimeFaces Mobile.

PrimeFaces, a popular JavaServer Faces (JSF) UI framework, can be used to quickly develop sophisticated applications for the enterprise and for small websites alike. It can also be utilized to harness the power of JQuery Mobile for creating views that scale well on mobile devices.

This article, which is Part 2 of a two-part series, focuses on how to efficiently build upon an existing PrimeFaces application to provide a usable interface for mobile devices. In Part 1 of this series, we took a look at how easy it is to build a robust enterprise application using the PrimeFaces JSF framework. In this part, we'll be developing a mobile user interface for an enterprise application using the PrimeFaces Mobile framework.

Specifically, we will build a mobile user interface for a swimming pool installation company named Acme Pools. It is our job to develop forms to display and accept input for customer, job, and pool information, as well as provide the ability to easily retrieve and update the data, as needed. For the context of this article, we will be making use of NetBeans 8.x IDE and PrimeFaces 5.x to build a mobile user interface for the AcmePools application.

Thinking About Mobile

Developing applications for a mobile device can be much different than developing for a standard desktop browser. There are various differences to think about, including the proper arrangement of components within a view so that everything fits nicely and remains functional. Moreover, you need to rethink the navigation so that there is not an application menu taking up real estate on the mobile device's screen. Mobile user interfaces are more effective with less clutter, so use of touch events to show and hide menus is oftentimes a good solution.

The PrimeFaces Mobile JSF framework provides sophisticated solutions for most mobile application requirements. Built upon JQuery Mobile, it provides a plethora of mobile-ready components that make wise use of the smaller screen, and the framework provides a number of touch events that can be utilized to optimize the mobile experience.

Getting Started

First, grab the AcmePools NetBeans project from GitHub. You can follow along with this article to develop the mobile user interfaces for the application.

PrimeFaces 5.x is bundled with the mobile framework in a single JAR file, so if your application is configured to make use of PrimeFaces, then you can begin to use the mobile framework without further configuration. That said, the AcmePools application uses Maven to incorporate the PrimeFaces framework, so no additional JAR files are needed.

PrimeFaces Mobile provides a render kit for building mobile application views. The mobile render kit transforms some of the standard PrimeFaces components, enabling them to become more mobile-friendly. It also includes a custom navigation handler to enhance mobile navigational transitions. To enable the custom navigation handler, open up the faces-config.xml file and add the following element as a child to the <application> element:

<navigation-handler>
    org.primefaces.mobile.application.MobileNavigationHandler
</navigation-handler>

PrimeFaces Mobile also includes a special namespace that must be imported within the mobile views to make use of mobile layout tags. The mobile render kit and layout tags are fully compatible with Facelets, so it is a good idea to create a mobile template, which can then be applied across all of the mobile views in your application.

To get started, open the AcmePools project within NetBeans, right-click the Web Pages folder and choose New, and then select Folder, naming the folder mobile. This folder will contain the mobile views for the AcmePools application.

Next, we want to create a template that can be utilized by all of the views within our mobile solution. Begin by right-clicking the mobile folder you just created, choosing New, and then selecting Facelets Template. Name the template mobile_template.xhtml, and save it (see Figure 1). At this point, it does not matter which layout style you choose, because we will overwrite it anyway.

primeface-pt1-f1
Figure 1. NetBeans New Facelets Template wizard

Open the newly created template, and add the following namespaces to the view:

xmlns:p="http://primefaces.org/ui"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:pm="http://primefaces.org/mobile"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"

Although optional, it is a good idea to add the passthrough namespace, because there might be some HTML5 pass-through attributes that we wish to apply to some components.

Next, go ahead and remove the two <div> sections and h:outputstylesheet tags that were generated by the IDE, because we do not wish to style our mobile views like the full web views.

Next, load the PrimeFaces Mobile render kit by adding the following tag directly after the opening <HTML> element:

<f:view renderKitId="PRIMEFACES_MOBILE">

To maintain flexibility throughout our template client views, we want to have the ability to add content to the head from any view, so add the following ui:insert line in the head section of the template.

<ui:insert name="header">Top</ui:insert>

Within the body section of the template, let's simply add another ui:insert line for now to enable template clients to add content to the view.

<ui:insert name="body">Default Mobile Body</ui:insert>

At this point, we could begin to add template clients (mobile views), but first we let's take a look at how we separate mobile navigation from the standard web application.

Navigating to the Mobile Views

This section will detail how to make a MobileNavigationController to ensure that mobile views are being used, rather than standard views. The concept is to have mobile users visit a starting page, or root view, each time they access the mobile application. In order to invoke the MobileNavigationController, we will initiate an action method whenever the mobile root view is accessed for the first time. The action method will then enable the mobile navigation and navigate the user's mobile browser to the mobile views. Moreover, we are going to take advantage of PrimeFaces Mobile custom navigation, and we will group related mobile pages together into single views for easier maintenance.

To begin implementing our mobile navigation, create a root view by right-clicking the mobile folder we created previously, selecting New, then choosing XHTML, and naming the view index.xhtml.

Next, let's create the MobileNavigationController class by navigating to the Source Packages folder in our project, right-clicking the com.acme.acmepools.jsf package, selecting New, and then choosing JSF Managed Bean (see Figure 2).

primeface-pt1-f2
Figure 2. Creating a JSF managed bean in NetBeans IDE

In the dialog box that opens, change Class Name to MobileNavigationController, set Scope to session, and leave all of the other default values. Click Finish to create the class.

Add a private boolean field to the class, and name it useMobile. Set the value to false within the field declaration. Now, generate accessor methods for the field by right-clicking the field name, selecting Refactor, and choosing Encapsulate Fields. Ensure that both Create Setter and Create Getter are selected, and click Finish (see Figure 3).

?

primeface-pt1-f3
Figure 3. Encapsulate Fields screen

Next, we need to add a method to this controller that we can use to initialize the mobile controller when a user visits the root view. Create a public method named initMobile(), which accepts no arguments and returns a string for navigational purposes (if needed). In the method implementation, simply set useMobile to true, and return a string value of NULL so that the same view is rendered. Listing 1 shows the entire method.

public String initMobile(){
    setUseMobile(true);
     return null;
}

Listing 1: initMobile() method

Let's add a JSF viewAction to the mobile/index.xhtml view, which will invoke the MobileNavigationController.initMobile() method when the root view is loaded. In this case, we will not navigate to another view, although a navigation-case could be added within the faces-config if we wanted to do so. Listing 2 shows the viewAction that should be added to the mobile/index.xhtml view.

<f:metadata>
    <f:viewAction action="#{mobileNavigationController.initMobile}"/>
</f:metadata>

Listing 2: Mobile root viewAction

Next, we can begin to develop the mobile UI.

Creating a Mobile UI

If you have experience using PrimeFaces with standard JSF projects, it is very easy to get started with PrimeFaces Mobile UI development. To begin, we will make the mobile/index.xhtml view the root of our mobile experience, so we will want to apply the mobile template that we created earlier, making the view a Facelets template client. To do so, if the Facelets namespace has not yet been added to the view, be sure to add it before proceeding.

xmlns:ui="http://xmlns.jcp.org/jsf/facelets"

Now that the namespace is in place, we can begin to utilize the Facelets tags. Make mobile/index.xhtml a template client by wrapping the view with the <ui:composition> tag, specifying the mobile template. Maintain the placement of the f:metadata element directly under the opening <html> tag.

To complete the templating for this view, add the <ui:define name="body"> tag as the first child tag within the <ui:composition> section within which the content for the view will be placed. Once finished, the view should look like Listing 3.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:pm="http://primefaces.org/mobile"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:pt="http://xmlns.jcp.org/jsf/passthrough">

    <f:metadata>
        <f:viewAction action="#{mobileNavigationController.initMobile}"/>
    </f:metadata>
    <ui:composition template="mobile_template.xhtml">
        <ui:define name="body">
            <!-- View Content will go here -->
        </ui:define>
      
    </ui:composition>
</html>

Listing 3: The mobile/index.xhtml view without content

Next, we want to load the initial application view, which displays a list of Acme Pools customers, within the mobile user interface. Figure 4 shows what the initial view of the AcmePools application looks like in the standard web application. As a first step in creating a mobile UI for AcmePools, we wish to make this view more mobile-friendly.

primeface-pt1-f4
Figure 4. Standard Acme Pools customer listing

Every PrimeFaces Mobile page is wrapped by the <pm:page> element. Each page can have its own ID, so we can place multiple <pm:page> sections into a single view. A standard mobile page should adhere to the following format:

<pm:page id="someId">
    <pm:header></pm:header>
    <pm:content>
    <!-- Content here -->
    </pm:content>
</pm:page>

In our solution, we will be creating two <pm:page> sections in the mobile/index.xhtml view. The first section will contain the customer listing, and the second will be the customer detail page.

To begin, create a page to contain the customer list within the <ui:define name="body"> section of the root mobile view by adding a pm:page section, and specifying an id of customerListing. Within the <pm:page> section, add a <pm:header> section, and specify the string Acme Pools Customer Listing. After the <pm:header>, add a <pm:content> section, which will contain the content for the customerListing mobile page.

If you look through the PrimeFaces Mobile showcase, you will see that the preferred component for listing data is the DataList. In fact, the standard DataTable component is not optimized for mobile UIs. Therefore, we will utilize a DataList component to display the list of customers.

To get started, we must obtain the data, and put it into a list. We will utilize the same controller methods that are used to load the initial customer listing in the standard application. Open up the com.acme.acmepools.jsf.CustomerController class, and find the getItems() method (see Listing 4). This method can be bound to our DataList component to load the customer data when the initial view is loaded, because it pulls all customers from the database and stores them into a list for later use.

public List<Customer> getItems() {
    if (items == null) {
        items = getFacade().findAll();
    }
    return items;
}

Listing 4: Method to populate the customer listing

Back in the mobile/index.xhtml view, add the p:dataList component within the content section, setting the value attribute to #{customerController.items} and the var attribute to items. To enable more functionality on mobile devices, make use of the HTML5 filter attribute by setting pt:data-filter="true". The filter will enable the user to type strings of text into the filter to shorten the list of customers to only those with text that matches the filter string.

Within the DataList, we need to create a large clickable area for each row of data so that we can drill into the customer details. To make this clickable area, create a p:commandLink component and embed customer information that we wish to display within the DataList. Set the action attribute of the commandLink to a controller method that will load an individual customer's data. In this case, we set the action to a method in CustomerController named loadCustomer(), which traverses the list of customers to find the selected customer object by customer ID.

Lastly, add a <pm:footer> section if you wish. Listing 5 shows the complete DataList implementation within the mobile/index.xhtml view.

<pm:page id="customerListing">
    <pm:header>
        Acme Pools Customer Listing
    </pm:header>
    <pm:content>
        <h:form id="indexForm">
            <p:panel header="Acme Pools Customer Listing">
                <p:dataList id="datalist" value="#{customerController.items}"
                            var="item" pt:data-filter="true">
                    <p:commandLink action="#{customerController.loadCustomer}"
                                   update=":customerInfo:customerInfoPanel">
                        <f:param name="customer" value="#{item.customerId}"/>
                        <h:panelGroup>

                            <h:outputText value="#{item.customerId} - #{item.name}"/>

                            <br/>
                            <h:outputText value="#{item.email}"/>

                        </h:panelGroup>
                    </p:commandLink>
                </p:dataList>
            </p:panel>
        </h:form>
    </pm:content>
    <pm:footer>
        Author: Duke
    </pm:footer>
</pm:page>

Listing 5: Mobile page including DataList of Acme Pools customers

When one of the customers in the view is selected, the #{customerController.loadCustomer} method is invoked, which searches through the contents of the Customer listing and finds the associated object based upon matching the customerId field.

Add a new public method to the CustomerController class to implement the search, and then return a navigational string to load the mobile/customerInfo.xhtml view. Listing 6 shows how an implementation of loadCustomer() might look. Note that we are searching through the list of customers rather than querying the database, because we want to limit the number of calls to the database that are made from a mobile device.

public String loadCustomer() {
    Map requestMap = FacesContext.getCurrentInstance().
            getExternalContext().getRequestParameterMap();
    String customer = (String) requestMap.get("customer");
    for(Customer customerObject:items){
        if(Objects.equals(customerObject.getCustomerId(), Integer.valueOf(customer))){
            selected = customerObject;
            break;
        }

    }
    // Query database...not the best performance for mobile
    //selected = ejbFacade.find(Integer.valueOf(customer));
    return "pm:customerInfo?transition=slide";
}

Listing 6: Loading the selected customer

Also note that the method returns the string pm:customerInfo?transition=slide. Any navigational string containing a prefix of pm will utilize the PrimeFaces Mobile navigation controller. Following the prefix is the id for the mobile page that you wish to display. The string also includes a mobile transition (?transition=slide), which basically adds an animated effect when the page transition takes place. For a full list of PrimeFaces transition options, please refer to the PrimeFaces documentation.

Lastly, to complete the initial customer listing, create a new page within the mobile/index.xhtml view by adding a new <pm:page> below the customerListing, and provide an id of customerInfo for the new page. This page will be used to display and edit the details for a selected customer.

Begin by adding the same <pm:header>, <pm:content>, and <pm:footer> sections as in the previous mobile page. Next, add a panel within the <pm:content> area, and provide an appropriate header.

We will create a user input form to display and edit the data, so add a h:panelGrid element, and specify two columns so that we can display a label and field for each row.

Now add an p:outputLabel and a p:inputText component pair for the following customer fields: name, addressLine1, addressLine2, and phone. Once completed, the panelGrid should look like the Listing 7:

<h:panelGrid columns="2">
    <p:outputLabel for="name" value="Name: "/>
    <p:inputText id="name" value="#{customerController.selected.name}"/>

    <p:outputLabel for="addressLine1" value="Address 1: "/>
    <p:inputText id="addressLine1" value="#{customerController.selected.addressline1}"/>

    <p:outputLabel for="addressLine2" value="Address 2: "/>
    <p:inputText id="addressLine2" value="#{customerController.selected.addressline2}"/>

    <p:outputLabel for="phone" value="Phone: "/>
    <p:inputText id="phone" value="#{customerController.selected.phone}"/>

</h:panelGrid>

Listing 7: Completed panelGrid

Next, add a p:commandButton for submitting any updates, and specify a value of Save, and an action of #{customerController.mobileUpdate}, because we will be adding a method named mobileUpdate() to the CustomerController class.

We need to set the ajax attribute of the commandButton to false, because we wish to have the user taken back to the original view once the form has been submitted successfully. Since the user needs to see some feedback after clicking the button, add a <p:growl> component to the top of the form.

We also want to add a link that the user can click to navigate back to the customer listing without submitting the form. Use a p:commandLink for this purpose, providing a string-based action that will simply navigate back to the customerListing page.

The full source code for the customerInfo page is shown in Listing 8.

<pm:page id="customerInfo">
    <pm:header>
        Acme Pools
    </pm:header>
    <pm:content>
        <p:panel id="customerInfoPanel" header="Acme Pools Customer Information">
            <h:form id="customerInfoForm">
                <p:growl id="messages"/>
                <h:panelGrid columns="2">
                    <p:outputLabel for="name" value="Name: "/>
                    <p:inputText id="name" value="#{customerController.selected.name}"/>

                    <p:outputLabel for="addressLine1" value="Address 1: "/>
                    <p:inputText id="addressLine1"
                     value="#{customerController.selected.addressline1}"/>

                    <p:outputLabel for="addressLine2" value="Address 2: "/>
                    <p:inputText id="addressLine2"
                     value="#{customerController.selected.addressline2}"/>

                    <p:outputLabel for="phone" value="Phone: "/>
                    <p:inputText id="phone" value="#{customerController.selected.phone}"/>

                </h:panelGrid>
                <p:commandButton value="Save" icon="ui-icon-disk" iconPos="top"
                                 action="#{customerController.mobileUpdate}"
                                 ajax="false"/>

                <p:commandLink action="pm:customerListing?transition=fade" value="Go Back"/>
            </h:form>
        </p:panel>
    </pm:content>
    <pm:footer fixed="true">
        <ui:include src="menu.xhtml"/>
    </pm:footer>
</pm:page>

Listing 8: Code for the customerInfo mobile page

The final piece of the puzzle for this page is the implementation of the mobileUpdate() method, which will be invoked when the Save button is clicked by the user. To add this method, open the CustomerController class and add the following code:

public String mobileUpdate(){
    update();
    FacesContext.getCurrentInstance().addMessage(null, 
                new FacesMessage(FacesMessage.SEVERITY_INFO,
                "Customer Successfully Updated","Success"));  
    return "/mobile/index";
}

Note that in this method implementation, we are simply wrapping the original update() method (created in Part 1 of this series) with a new message and a navigational return string for the mobile application.

We've now successfully created the first mobile page of the AcmePools mobile application. If you run the application now, and traverse to the URL http://localhost:8080/AcmePools/faces/mobile/index.xhtml, you should see a view resembling Figure 5 in your browser.

primeface-pt1-f5
Figure 5. AcmePools mobile customer listing

When a customer is selected from the listing, a page that looks like Figure 6 will be displayed.

primeface-pt1-f6
Figure 6. Customer detail page

When a record is saved, the growl component will display a success message, and the user will be taken back to the original customer listing.

Note: For an exceptional mobile test viewer, install the Google Chrome browser plugin for NetBeans IDE. The browser plugin not only enables live content editing, but it also allows you to easily change the size of the view according to the size of screen being targeted for development (see Figure 7).

primeface-pt1-f7
Figure 7. NetBeans IDE Chrome plugin

Follow the guidelines above to develop the different mobile views for your application. I recommend trying out each of the navigational transitions and also the touch events to see what works best for your application.

Creating a Navigation Menu

To create nonintrusive navigation for our mobile application, we need to determine the best positioning for a menu in a mobile layout. PrimeFaces Mobile is bundled with some great components to suit this purpose, including the TabMenu, Menu, and OverlayPanel. It is even possible to develop custom solutions, such as swipeable menus that can be presented by swiping towards the center of the screen. In this application, we will add a TabMenu to the footer of our pages.

Before we add the menu, we need to create the additional application views. Specifically, the mobile/pools.xhtml and mobile/jobs.xhtml views need to be created. Do so by right-clicking the mobile folder, choosing New from the contextual menu, and selecting XHTML. Name each view accordingly, repeating the process to create both views. Once complete, open each view and overwrite the contents with an empty mobile view, which is shown in Listing 9.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:pm="http://primefaces.org/mobile"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:pt="http://xmlns.jcp.org/jsf/passthrough">

        <ui:composition template="mobile_template.xhtml">
        <ui:define name="body">
            <pm:page>
                <pm:header>
                </pm:header>
                <pm:content>
                </pm:content>
                <pm:footer>
                    
                </pm:footer>
            </pm:page>
        </ui:define>

    </ui:composition>
</html>

Listing 9: Empty mobile view

To create the menu, first add a new XHTML page into the mobile folder of our application, and name it menu.xhtml. Next, add the PrimeFaces Mobile namespace to the view. We will embed this menu into the <pm:footer> sections of our mobile pages. We can begin by adding a form element as the first child element inside of the <html> section.

To create a TabMenu, first specify the <p:tabMenu> tag within the form, and then specify one or more <p:menuItem> components within that. For this application, add three menuItem components for navigating to each of the mobile views within our application: pools.xhtml, index.xhtml, and jobs.xhtml.

To perform the navigation, add an action attribute to each of the menuItem components, and specify a method named mobileNavigtionController.menuNavigation that will return the desired navigational string. We will be passing a string as an argument to this method, as you will see in Listing 10. We will also specify the activetabindex for the menu so that the correct button is highlighted, depending upon the view that is currently onscreen.

To write the navigational action method, open up the MobileNavigationController, and add a new private int field identified as activetabindex. We will use this field to keep track of the currently selected menu item. Create the getter and setter methods for accessing the newly created field.

Next, create a public method that returns a String, accepts a single string-based argument named view, and name the method menuNavigation. In the implementation, utilize a switch statement to navigate to the appropriate view, depending upon the string that is passed in as an argument. At the same time, set the activetabindex accordingly. The code should look like that in Listing 10.

public String menuNavigation(String view){
    switch(view){
        case "POOLS":
            setActivetabindex(1);
            return "/mobile/pools";
        case "JOBS":
            setActivetabindex(2);
            return "/mobile/jobs";
        case "HOME":
            setActivetabindex(0);
            return "/mobile/index";
        default:
            setActivetabindex(0);
            return "/mobile/index";
    }

}

Listing 10: Menu navigation action method

Back in the TabMenu, add the activetabindex attribute to the <p:tabMenu> element, and specify the value of #{mobileNavigationController.activetabindex('STRING')}, passing the appropriate menu item value in place of STRING. The completed TabMenu looks like the code shown in Listing 11.

<h:form id="menuForm">
    <p:tabMenu activeIndex="#{mobileNavigationController.activetabindex}">
      <p:menuitem value="Home" icon="ui-icon-home" ajax="false"
                  action="#{mobileNavigationController.menuNavigation('HOME')}"
                  iconPos="top"/>
      <p:menuitem value="Pools" icon="ui-icon-home" ajax="false"
                  action="#{mobileNavigationController.menuNavigation('POOLS')}"
                  iconPos="top"/>
      <p:menuitem value="Jobs" icon="ui-icon-home" ajax="false"
                  action="#{mobileNavigationController.menuNavigation('JOBS')}"
                  iconPos="top"/>
  </p:tabMenu>
</h:form>

Listing 11: TabMenu for navigation

Now we are ready to embed the new menu into the footer sections of our mobile pages. Do so by adding a <ui:include> tag, as shown below, inside the <pm:footer> section within each mobile view. Also specify the fixed=true attribute for the footer, because this will allow the footer to remain onscreen at all times. If a user touches somewhere on the screen, the menu will slide down and become hidden.

<pm:footer fixed="true">
    <ui:include src="menu.xhtml"/>
</pm:footer>

The resulting mobile view for index.xhtml will look like Figure 8, once loaded in the browser.

primeface-pt1-f8
Figure 8. Complete index.xhtml mobile view

More Mobile Features

PrimeFaces Mobile includes a series of features to help customize the mobile user experience. For instance, the lazy loading feature can be added to multipage views so that each mobile page within the view can be loaded on demand to enhance performance. PrimeFaces Mobile also enhances each of the mobile components with out-of-the-box Ajax support, so that state changes do not affect the rendering of the mobile UI.

Swipe and TapHold touch events are built into PrimeFaces Mobile. These can be handy when working with a DataList. For instance, you can choose to implement a solution where detailed data is displayed in a pop-up when a data record is tapped on and held. Since PrimeFaces Mobile is built on top of JQuery Mobile, it is easy to integrate standard JQuery Mobile touch events into an application as well.

If you want to implement a custom look and feel for your mobile application, the PrimeFaces Mobile framework also includes custom theming. Built on top of the JQuery Mobile CSS framework, this option allows developers to create custom theme JAR files so that themes can be applied to one or more applications.

Conclusion

Application developers can no longer ignore the mobile market. There is no doubt that mobile devices such as phones and tablets are the way of the future, so it is important to optimize applications for use on mobile platforms.

To that end, PrimeFaces Mobile is a great option for those who develop Java EE applications utilizing the JSF framework. Not only is PrimeFaces Mobile bundled with dozens of custom components for creating sophisticated mobile user interfaces, but it also contains a number of features that make implementation of touch-enabled views very easy.

Moreover, using PrimeFaces Mobile enables enterprise developers to share business logic between standard and mobile views, thereby enhancing their productivity. For more information, please visit primefaces.org, and keep an eye on my blog.

See Also

About the Author

Josh Juneau works as an application developer, system analyst, and database administrator. He primarily develops using Java and other Java Virtual Machine (JVM) languages. Josh is a technical writer for Oracle Technology Network and Java Magazine. He was a coauthor of The Definitive Guide to Jython, published by Apress in 2010. He also coauthored PL/SQL Recipes (Apress 2010) and Java 7 Recipes (Apress 2011). He recently authored Java EE 7 Recipes and Introducing Java EE 7, which were published by Apress in 2013, and Java 8 Recipes, which was published in 2014.

Please feel free to e-mail Josh if you have questions.

Join the Conversation

Join the Java community conversation on Facebook, Twitter, and the Oracle Java Blog!