Liferay Faces Portal 3.0.2, Bridge Impl 4.1.1, Bridge Ext 5.0.2 Released

Company Blogs May 15, 2018 By Kyle Joseph Stiemann Staff

Liferay Faces Portal 3.0.2, Bridge Impl 4.1.1, Bridge Ext 5.0.2 Released

Liferay Faces Portal 3.0.2, Bridge Impl 4.1.1, and Bridge Ext 5.0.2 have been released with support for PrimeFaces 6.2, PrimeFaces p:fileUpload mode="simple" (thanks to community member Yeray Rodriguez!), URLs with spaces and more!

Liferay Faces Portal 3.0.2 Release Notes Highlights

  • [FACES-3242] - Upgrade to PrimeFaces 6.2
  • [FACES-3243] - portal: components with javascript (captcha, inputRichText, etc) fail to update with Ajax in Liferay 7.0 GA5

Full Release Notes

Liferay Faces Bridge Impl 4.1.1 Release Notes Highlights

  • [FACES-3242] - Upgrade to PrimeFaces 6.2
  • [FACES-3264] - PrimeFaces file upload fails with PrimeFaces 6.2
  • [FACES-3250] - Primefaces file upload mode=simple does not work (thanks to community member @yerayrodriguez for this contribution!)
  • [FACES-2958] - bridge creates invalid URLs when view params contain spaces in liferay
  • [FACES-3261] - The wrong content type of "text/html" is set for execute "@all" Ajax responses

Full Release Notes

Liferay Faces Bridge Ext 5.0.2 Release Notes Highlights

  • [FACES-2958] - bridge creates invalid URLs when view params contain spaces in liferay

Full Release Notes

Archetypes

Along with these updates, all of our archetypes have been updated to the latest appropriate Liferay Faces, PrimeFaces, and Mojarra artifacts.

JSFSPEC #1433

In order to avoid JSFSPEC #1433, we strongly recommend that all JSF projects update to the latest appropriate Liferay Faces and Mojarra artifacts. JSF 1.2 projects should also add the following context-param to each web.xml file (Liferay Faces Util 2.1.0 and 3.1.0 automatically add the context-param for JSF 2.1+ projects via web-fragment.xml):

<context-param>
    <param-name>javax.faces.ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE</param-name>
    <param-value>true</param-value>
</context-param>

Please report any issues with this new release in JIRA and ask any questions in our forums.

Key Takeaways From JavaOne 2017 Talks

Technical Blogs October 6, 2017 By Kyle Joseph Stiemann Staff

Key Takeaways From JavaOne 2017 Talks

Here are some of the key takeaways that I learned from the talks I attended at JavaOne 2017:

How to Use Java Cryptography API Securely

by Mansi Sheth (video)

The Java Cryptography API is quite powerful and up-to-date as of Java 8, however there are some pitfalls when using it. Mainly, the JavaDoc examples and API defaults tend to use insecure, old crypto standards. Also for backwards compatibility, the Crypto API provides options that are not recommended or are insecure or deprecated. However, the API does provide modern, secure crypto options, so developers should check the best practices to ensure that they are using modern options before employing the Cryptography API.

Servlet 4.0: A New Twist On An Old Favorite

by Ed Burns and Shing wai Chan (video)

Servlet 4.0 supports HTTP/2 and specifically Servlet Push. Servlet Push allows the servlet to send resources such as CSS and JS to the browser along with the html response to avoid unnecessary extra requests. Frameworks such as JSF will be able to take full advantage of this feature since they know which resources their view requires before returning the response. Servlet 4.0 has also added support for the HTTP trailer—which can be used to provide a checksum for the response among other things—and mapping discovery which can be used to determine how the current servlet was obtained.

JavaOne Monday October 2, 2017 Keynote (video)

  • Intel is optimizing hardware for Java and has released a few open source libraries for use cases such as persistent memory.
  • Java is still one of the world’s most popular programming languages.
  • Oracle is providing the open-source Fn project to support serverless computing.
  • Oracle JDK and Open JDK will be merged.
  • Java SE 9 provides a new module system and linker so that smaller custom JRE’s can be built to include only the modules that are necessary.
  • Java SE is now on a 6 month release cycle.

Understanding Java Garbage Collection

by Gil Tene (video)

There are many options for garbage collection strategies in Java including copying collection or mark -> sweep -> compact. It’s difficult (but possible) to implement a responsive garbage collector that does not pause the entire JVM while performing garbage collection (since memory is still growing if the JVM is not paused). Testing garbage collection is difficult since many JVMs will attempt to delay garbage collection as long as possible (usually until after the test is done).

The Secret Sauce of Successful Teams

by Sven Peters (video)

Good teams provide psychological safety to explore (potentially bad) ideas and make mistakes. Good teams have at least some overarching schedule and an ability to grade themselves on whether they accomplished their goals (for example using OKRs).

JSF 2.3 in Action

by Kito Mann

JSF 2.3 includes many new features features and additions (several of which were contributed by community members Bauke Scholtz and Arjan Tijms). To name a few: f:websocket, h:commandScript, f:importConstants, ui:repeat begin, end, and step attributes which allow for iteration without a data model, and CDI injection of JSF objects like FacesContext. For a more complete list, see Arjan Tijm’s blog post What’s new in JSF 2.3?.

The Art of Performance Tuning

by Jonathan Ross

Since Java and the JVM are so complex, use the scientific method rather than intuition to test and improve performance. The Open JDK JMH framework allows developers to write performance regression tests.

Java Secure Coding Guidelines

by Sean Mullan

Oracle provides Secure Coding Guidelines for Java SE. Deserializing untrusted data can allow remote or malicious code to be executed on the JVM.

The Power and Practicality of Immutability

by Venkat Subramaniam

Immutability can make code simpler to reason about, allow compiler optimizations, and be exploited for easy parallelism.

SSL/TLS for Mortals

by Maarten Mulders (video)

Encryption allows for secure interactions on the web. Certificate authorities are needed to verify that data is being sent to legitimate sites. However, certificate authorities can be compromised, so browsers need to keep up-to-date information on trusted certificate authorities as well.

Scale Up With Lock-Free Algorithms

by Roman Elizarov (video)

Lock-free algorithms can be implemented with atomic variables using the compareAndSet() method inside a while(true) loop. Lock-free algorithms tend to perform better than locking algorithms in read-heavy real-world scenarios (as opposed to write-heavy).

The Anatomy of Java Vulnerabilities

by Steve Poole (video)

Vulnerabilities include bugs, features, and developer tools that a hacker can exploit.

Portlet 3.0 Deep Dive (Teaser)

I’m planning on including the Portlet 3.0 Deep Dive video in a larger blog post about Portlet 3.0 in general. So look forward to that soon.

Conclusion

One of the biggest takeaways from JavaOne was the commitment to open sourcing even more technology including TCKs and specifications that are moving to the Eclipse Foundation (as EE4J). Learning about all these technologies and best-practices was fun, but the best part of JavaOne was talking to JavaEE experts like Kito Mann and Ed Burns and listening to the problems that JavaEE devs are solving today.

Hidden Features of Liferay Faces: The nativeWhenMobile attribute of alloy:inputDate and alloy:inputTime

Technical Blogs September 26, 2017 By Kyle Joseph Stiemann Staff

Hidden Features of Liferay Faces: The nativeWhenMobile Attribute of alloy:inputDate and alloy:inputTime

One of my favorite lesser-known features of Liferay Faces Alloy is the the nativeWhenMobile attribute of alloy:inputDate and alloy:inputTime.1 When a user on a mobile device views an alloy:inputDate or alloy:inputTime with nativeWhenMobile="true", the inputDate or inputTime component will render an input with type="date" or type="time" repectively instead of the normal AlloyUI JavaScript DatePicker or TimePicker.2 The advantage of rendering a input with type="date" or type="time" on mobile devices is that it causes the device to utilize the built-in, touch-friendly date picker or time picker of the device’s OS. Here’s a visual comparison of the rendered pickers on different devices:

alloy:inputDate
On Desktop On iPhone On Android

 

alloy:inputTime
On Desktop On iPhone On Android

If you want to see a live demo of this feature, navigate to the Liferay Faces Alloy Showcase General examples for alloy:inputDate or alloy:inputTime on a mobile device.

How can you take advantage of the UX improvement of native date or time pickers on mobile devices? Well, if you are using Liferay Faces Alloy’s inputDate or inputTime in your JSF application, mobile users are already using native pickers! The nativeWhenMobile attribute defaults to true so it is turned on by default. With nativeWhenMobile="true", you can display a powerful Liferay-themed input and picker for larger devices while presenting users with a familiar, touch-friendly, native date or time picker on mobile devices.

  1. Even I neglected to mention this feature in my own blog about the Liferay Faces Alloy input components! Shame on me!

  2. Although I implemented this feature, I cannot take credit for coming up with the idea. The Liferay Faces Team stole borrowed the idea from the core portal’s liferay-ui:input-date component. This feature was implemented in liferay-ui:input-date by Eduardo Lundgren.

Farewell Juan!

General Blogs February 17, 2017 By Kyle Joseph Stiemann Staff

Farewell Juan!

Juan Gonzalez announced that today is his last day as a Liferay employee. While he’ll still be part of the Liferay community, I think this is a nice opportunity for us to thank him for his work at Liferay and to wish him well on his next endeavor.


Juan,
After working with you for several years, I’m sad to see you go. You’re an incredibly passionate and hard worker. Thanks to your dedication, Liferay 7 correctly supports several servlet features (many of which were required for Liferay Faces to be compatible with Liferay 7). Thanks to your passion, Liferay Faces developers can access portal taglib features through tags like portal:inputSearch (not to mention all the Liferay Faces Portal bugs you’ve fixed). Thanks to your involment in the forums, countless people in the Liferay community have had their problems solved (you’ve written almost 3k posts and are user #4 overall).

Juan, the Liferay community, the Liferay Faces project, and Liferay itself would not be nearly as great without your contributions. And I’ve personally admired and sought to emulate your productivity, passion, and community involvement. Thanks for all your hard work!

Farewell Juan!

- Kyle

Improving Test Performance on Liferay

Technical Blogs February 15, 2017 By Kyle Joseph Stiemann Staff

Improving Test Performance on Liferay

Recently, we upgraded the JSF Portlet Bridge Test Compatibility Kit (TCK) from Selenium 1.0 to our new test framework which uses Selenium 2.53. The TCK contains about 220 tests, and on Liferay 7.0 before we upgraded, it took around 8 minutes and 30 seconds to execute. In contrast, the TCK took 1 minute and 30 seconds to run on Apache Pluto, the portlet container reference implementation. In order to speed up test execution for Liferay Portal, we decided to try a few simple tricks and changes to reduce the total test time, and… we succeeded! Here’s a breakdown for how fast each browser ran the TCK on my machine before our upgrade, after our upgrade, and after we tweaked the TCK with some Liferay specific tricks:

Browser Selenium 1.0 Test Time Selenium 2.53 Test Time Selenium 2.53 w/Exclusive
Window State Test Time
HtmlUnit* - - ~00:00:45
Chrome - ~00:04:30 ~00:01:30
Firefox ~00:08:30 (w/FF v21.0) ~00:06:00 (w/FF v46.0) ~00:02:30
JBrowser*
(experimental)
- - ~00:02:30
PhantomJS* - ~00:16:15 ~00:10:30

* Headless browser.

As you can see, we made some pretty big improvements just by upgrading to a modern version of Selenium. Running tests with HtmlUnit also provided a nice boost over other browsers. Before I talk in-depth about HtmlUnit though, I want to begin by explaining the Liferay-specific tweaks and tricks that we used to speed up the TCK. These techniques are specific to Liferay but not to Selenium or HtmlUnit, so they may be useful in improving the performance of Liferay portlet tests regardless of the test framework or browsers used.

Exclusive Window State

The main performance boost is thanks to Liferay’s custom “exclusive” window state.1 In Liferay, any portlet can be accessed in the exclusive state with a render URL containing the portlet’s id (p_p_id) and p_p_state=exclusive:

http://localhost:8080/my/portlets/page?p_p_id=myPortletName_WAR_myPortletWarName&p_p_lifecycle=0&p_p_state=exclusive

Liferay’s exclusive window state feature was created when Liferay only supported Portlet 1.0, and it provides similar functionality to the RESOURCE_PHASE of the Portlet 2.0 lifecycle. When Liferay Portal returns a portlet’s markup in the exclusive state, the markup contains only the portlet’s markup fragment without <html>, <head>, or <body> tags. Thankfully, every browser we use for testing handles the incomplete markup gracefully and renders the portlet testable. Providing the bare-bones portlet markup, the exclusive state doesn’t render any portal markup or frontend resources (such as CSS or JS). This greatly reduces the time it takes for a browser to load the page. The exclusive window state is useful for quickly testing backend functionality and rendering. I would not recommend testing portlets with complex JavaScript or CSS in the exclusive state. In fact, if you want to test a portlet with any external JavaScript resources at all, you will need to make sure that the resource’s script tag is rendered in the portlet’s body (<div>) markup rather than the portal’s <head> section (which isn’t rendered).2 Certainly, using the exclusive state will not work for all tests, but it can provide significant speed improvements for certain tests.

Pop Up Window State

If you cannot easily move your portlet’s resources into your portlet’s body or if you rely on Liferay Portal’s frontend features (JS and/or CSS), try using the “pop_up” window state instead. In Liferay, any portlet can be accessed in the pop up state with a render URL containing the portlet’s id (p_p_id) and p_p_state=pop_up:

http://localhost:8080/my/portlets/page?p_p_id=myPortletName_WAR_myPortletWarName&p_p_lifecycle=0&p_p_state=pop_up

When a portlet is in the pop up state, the portal renders the <html>, <head>, and <body> tags including JavaScript and CSS resources. However, as with the exclusive state, the portal does not render any portal markup or portlets besides the one referenced in the URL. Even though using the exclusive state yielded greater performance benefits, using the pop up state still significantly sped up our tests (probably by about 25%).

Of course, neither of these two states should be used for testing portlets which may interact with each other, since they only render a single portlet. These states also don’t help if you are trying to test other window states (as we do in the TCK). However, while upgrading the TCK, we found another way you can speed up your tests if you are using Selenium.

HtmlUnit

Of all the Selenium compatible browsers that we test with, HtmlUnit is by far the fastest. And since HtmlUnit is headless, it can be run on a CI server without a window manager. HtmlUnit is not perfect. Its JavaScript engine has trouble running more complicated or cutting edge code, so I wouldn’t recommend it for testing newer browser features like the History API (which SennaJS uses) or HTML5. Nonetheless, it is an excellent browser for testing simple pages quickly. So how do you use HtmlUnit? Well if you are using Selenium, simply add the HtmlUnit dependency to your project (make sure you get the latest one):

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>htmlunit-driver</artifactId>
    <version>2.23.2</version>
    <scope>test</scope>
</dependency>

Then just change your WebDriver implementation to HtmlUnitDriver:

WebDriver webDriver = new HtmlUnitDriver();

The End.

Well… not really. HtmlUnit is a simple tool, but unfortunately configuring it to behave like every other browser is over-complicated and poorly documented. First, you will need to specify the following dependencies to avoid several NoClassDefFoundError/ClassNotFoundException issues:

<dependency>
    <groupId>xml-apis</groupId>
    <artifactId>xml-apis</artifactId>
    <version>1.4.01</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.eclipse.jetty.websocket</groupId>
    <artifactId>websocket-client</artifactId>
    <version>9.2.18.v20160721</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.2</version>
    <scope>test</scope>
</dependency>

Second, I recommend disabling (or filtering) HtmlUnit’s incredibly verbose logging:

// Uncomment to enable HtmlUnit's logs conditionally when the log level is FINER or higher.
// if (logLevel.intValue() > Level.FINER.intValue()) {
LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log",
    "org.apache.commons.logging.impl.NoOpLog");
Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);
Logger.getLogger("org.apache.commons.httpclient").setLevel(Level.OFF);
// }

Third, you should extend HtmlUnitDriver:

public class CustomHtmlUnitDriver extends HtmlUnitDriver {

Extending HtmlUnitDriver allows you to force HtmlUnit not to throw exceptions when JavaScript errors occur, and it allows you to silence CSS errors:

@Override
protected WebClient modifyWebClient(WebClient initialWebClient) {

    WebClient webClient = super.modifyWebClient(initialWebClient);

    // Don't throw exceptions when JavaScript Errors occur.
    webClient.getOptions().setThrowExceptionOnScriptError(false);

    // Uncomment to filter CSS errors.
    // if (logLevel.intValue() > Level.FINEST.intValue()) {
    webClient.setCssErrorHandler(new SilentCssErrorHandler());
    // }

    return webClient;
}

Fourth, you should note that HtmlUnit does not load any images by default,3 so any tests which require images to be loaded should manually call a method like the one below to load them:

public void loadImages() {

    HtmlPage htmlPage = (HtmlPage) lastPage();
    DomNodeList<DomElement> imageElements = htmlPage.getElementsByTagName("img");

    for (DomElement imageElement : imageElements) {

        HtmlImage htmlImage = (HtmlImage) imageElement;

        try {

            // Download the image.
            htmlImage.getImageReader();
        }
        catch (IOException e) {
            // do nothing.
        }
    }
}

Finally, always initialize HtmlUnit with JavaScript enabled (and emulate a popular browser):

WebDriver webDriver = new CustomHtmlUnitDriver(BrowserVersion.FIREFOX_45, true);

If you want a complete example of how we use HtmlUnit in Liferay Faces, see HtmlUnitDriverLiferayFacesImpl.java and Browser.java.

Hopefully, the advice in this post will help you speed up your tests in Liferay. If you’ve found any other tricks that improve your tests’ performance, please post them in the comments below.


  1. Liferay Faces Team Lead, Neil Griffin, suggested using the exclusive window state to speed up tests.
  2. Liferay Faces Bridge automatically handles this case and moves JS and CSS resource markup into the portlet’s body (<div>) if the exclusive state is being used.
  3. Once HtmlUnit 2.25 and a compatible HtmlUnitDriver are released, you will be able to configure HtmlUnit to download all images automatically.

Single Page Applications with SennaJS and Liferay Faces

Technical Blogs October 17, 2016 By Kyle Joseph Stiemann Staff

Single Page Applications with SennaJS and Liferay Faces

One of Liferay 7’s most exciting new features is SennaJS, a Single Page Application engine. SennaJS makes the portal more user-friendly in many ways. For example, when a link is clicked and navigation occurs, SennaJS requests the necessary portlet markup via XHR and renders it in the browser so that the whole portal page is not reloaded. As part of our latest release of Liferay Faces, we’ve added support for SennaJS so that JSF portlet developers can take advantage of this amazing feature.

How do I use SennaJS with Liferay Faces portlets?

Liferay Faces Bridge enables support for SennaJS in Liferay 7 by default. Utilizing SennaJS is as simple as using h:link, h:outputLink, or any other component which renders an <a> tag.1 If the link navigates to another page in your portal, SennaJS will automatically handle the navigation and cause an XHR GET which will load only the changed parts of the page. You can try this live in the Liferay Faces Showcase h:link example by clicking the To Param page > link. Clicking the link causes an XHR GET via SennaJS which is shown visually with a blue loading bar at the top of the page. You can compare this to a full-page GET by changing the end of the URL from param back to navigation and hitting enter. The full-page navigation is not only slower, but it causes more blinking and changes on the page.

Disabling SennaJS

Although SennaJS improves the user experience, it may be unnecessary for (or, rarely, incompatible with) certain use cases. If your portlet requires that SennaJS be disabled, then simply add <single-page-application>false</single-page-application> to the <portlet> section of your liferay-portlet.xml. You can also disable SennaJS on a portal-wide basis (by adding javascript.single.page.application.enabled=false to your portal-ext.properties file) or an element by element basis (Ex: <a data-senna-off="true">).

Under The Hood: How Liferay Faces Integrates with SennaJS

The Liferay Faces team worked closely with Bruno Basto, a Liferay front-end engineer, and Eduardo Lundgren, one of the creators of SennaJS, to ensure that Liferay 7’s usage of SennaJS would be compatible with Liferay Faces. Fortunately, SennaJS and Liferay 7 were already working together elegantly before we attempted to add Liferay Faces to the mix. Liferay 7 required only a few minor tweaks to allow Liferay Faces to take advantage of SennaJS. Bruno Basto implemented these changes. Thanks to him, SennaJS avoids loading duplicate resources in the <head> section by automatically tracking all CSS and JS resources and assuming that JS resources should not be unloaded.2,3

Since SennaJS is enabled by default in Liferay 7, the Liferay Faces team only needed to disable it for JSF components which were incompatible with its features. SennaJS assumes all links cause navigation, and it uses an XHR to obtain the markup that would otherwise be obtained via a full-page GET. Since JSF commandLink components are intended to submit a form rather than simply navigate to another page, they must not invoke SennaJS’s functionality. Likewise, SennaJS automatically causes forms to submit via XHR. However this feature is not compatible with JSF, since JSF expects to be in total control of form submissions.4 In order to avoid these incompatibilities, we used the data-senna-off attribute to disable SennaJS for all commandLinks and forms in Liferay 7.

With the minor changes listed above, Liferay Faces now allows JSF developers to enjoy the major benefits of SennaJS in Liferay 7!

  1. …with the exception of commandLink components. See the “Under the Hood” section for more details.
  2. Even though SennaJS tracks all the JavaScript files that are loaded, there is no way for it to generically unload all the components from those files, so it assumes it should not unload a JS element. This has the beneficial side effect of not reloading the same JS multiple times when a user navigates from one page to another and back again with SennaJS.
  3. All of these improvements benefit Liferay portlet developers who use JSP technology as well.
  4. Of course, JSF has its own functionality for submitting forms via ajax.

How can I build Liferay 7.0 from source?

Technical Blogs April 27, 2016 By Kyle Joseph Stiemann Staff

How can I build Liferay 7.0 from source?

To build Liferay 7.0 from source:

  1. Obtain the source code:*

    git clone -b 7.0.x https://github.com/liferay/liferay-portal.git \
        --depth 1
    
  2. Navigate to your new liferay-portal directory:

    cd liferay-portal/
    
  3. In your app.server.${yourname}.properties file, set the location where you want Liferay 7.0 to be built:

    echo "app.server.parent.dir=/path/to/liferay-portal" \
        > "app.server.$(whoami).properties"
    
  4. Optional: If you want to build the Wildfly 10 bundle rather than the default Tomcat bundle:

    1. Add app.server.type=wildfly to app.server.${yourname}.properties:

      echo "app.server.type=wildfly" \
          >> "app.server.$(whoami).properties"
      
    2. Download and unzip Wildfly in your ${app.server.parent.dir} directory:

      ant -f build-dist.xml unzip-wildfly
      
  5. Build Liferay 7.0:

    ant clean all
    

Now you should be able to start up Tomcat (or Wildfly), and Liferay 7.0 should be accessible at localhost:8080.

* I recommend getting a shallow clone since Liferay is a huge project with massive amounts of history and commits. Shallow cloning speeds up the clone process quite a bit.

New Liferay Faces Release - FacesRequestContext

Technical Blogs November 10, 2015 By Kyle Joseph Stiemann Staff

New Liferay Faces Release - FacesRequestContext

Update: There is now a runnable example of the FacesRequestContext in the Liferay Faces Showcase.

The Liferay Faces GA6 release contains many new Alloy and Portal components, which members of the Liferay Faces Team have blogged about. But components are not the only new features included in the latest release of Liferay Faces. The Liferay Faces Team has added the FacesRequestContext,1 a new feature which facilitates adding client scripts programmatically on the server-side.

FacesRequestContext is a ThreadLocal singleton like FacesContext which can be called on the server to add scripts on the client. For example, to execute an alert() on the client-side from a managed bean, you can use FacesRequestContext.addScript() like so:

FacesRequestContext.getCurrentInstance().addScript("alert('Added in managed bean.');");

In the response of the current request, the script will be written at the bottom of the page.2 If you need to run a script programmatically from a managed bean or some other server-side code, you can call FacesRequestContext.addScript() to add the script in the response.

Here’s a more robust example.3 The following dialog has a form which requires that the user write their name:

<alloy:dialog clientKey="dialog" hideIconRendered="false">
    <alloy:form>
        <alloy:inputText required="true" value="#{bean.name}" />
        <alloy:commandButton action="#{bean.action}"
            render="@form" value="Submit" />
    </alloy:form>
</alloy:dialog>

If the user has submitted their name, the dialog should be closed, and if the user has clicked submit without writing their name, the dialog should remain open. In the managed bean, FacesRequestContext.addScript() can be called to close the dialog when a valid name has been submitted:

public void action() {
    if (name != null) {
        FacesRequestContext.getCurrentInstance()
            .addScript("Liferay.component('dialog').hide();");
    }
}

Now the dialog will only close when the user’s name is not null.

FacesRequestContext is one of the many new features added in Liferay Faces GA6. Please check out the other Liferay Faces blogs by Neil, Juan, and Vernon, the Liferay Faces Showcase, the Liferay Faces page on dev.liferay.com, the Liferay Faces VDLdoc, and the Liferay Faces JavaDoc for more details about all the features of Liferay Faces.

  1. Unfortunately, there is not currently a showcase page for FacesRequestContext. However, the next release of the Liferay Faces Showcase will demonstrate a live working example of FacesRequestContext (see FACES-2504 for more details).

  2. In a full page response, the script will be written in a <script> tag which will be rendered immediately before the closing </body> tag. In an Ajax partial response, the script will be rendered in the the <eval> section of the partial response.

  3. This example was inspired by Nestor Cruz’s forum post which had a similar example.

Under The Hood: The Liferay Faces Generator

Technical Blogs September 24, 2015 By Kyle Joseph Stiemann Staff

Under The Hood: The Liferay Faces Generator

The Liferay Faces Generator is a code generation tool used to create custom JavaServerTM Faces (JSF) components (such as the new Liferay Faces Alloy components). The purpose of the generator is to automatically write the boilerplate code necessary to create each custom JSF component. The Liferay Faces team uses the generator to produce taglib.xml declarations (including component configuration and documentation), attribute getters and setters, rendering code for AlloyUI attributes, and many minor aspects of custom components.

The Generator's tags.xml File

JSF component developers are intimately familiar with the JSF taglib.xml file, which is used to declare custom components, and each taglib.xml file already contains much of the information necessary to generate components. In order to take advantage of the familiar syntax and helpful information in taglib.xml files, the Liferay Faces Generator takes as input a tags.xml file which uses a purposefully similar syntax to a taglib.xml file to declare components for the generator. The tags.xml file also adds some helpful extensions to the taglib.xml schema to make generation easier.

Here's an example tags.xml entry:

<tag>
    <description><![CDATA[This is an <code>exampleTag</code>.]]></description>
    <tag-name>exampleTag</tag-name>
    <attribute>
        <attribute-extension>
            <default-value>"exampleDefault"</default-value>
        </attribute-extension>
        <description>
            <![CDATA[This is an <code>exampleAttribute</code>.]]>
        </description>
        <name>exampleAttribute</name>
        <type>java.lang.String</type>
    </attribute>
    </tag-extension>
        <extends-tags>styleable altInherited</extends-tags>
        <parent-class>
            <![CDATA[javax.faces.component.UIComponentBase]]>
        </parent-class>
        <renderer-parent-class>
            <![CDATA[javax.faces. render.Renderer]]>
        </renderer-parent-class>
        <since>2.0</since>
    </tag-extension>
</tag>

The above code will generate the following output in the taglib.xml file:

<tag>
    <description><![CDATA[This is an <code>exampleTag</code>.]]></description>
    <tag-name>exampleTag</tag-name>
    <component>
        <component-type>
            com.liferay.faces.example.exampletag.ExampleTag
        </component-type>
        <renderer-type>
            com.liferay.faces.example.exampletag.ExampleTagRenderer
        </renderer-type>
    </component>
    <attribute>
        <description>
            <![CDATA[HTML passthrough attribute specifying alternative
            information about the rendered HTML element.]]>
        </description>
        <name>alt</name>
        <required>false</required>
        <type><![CDATA[java.lang.String]]></type>
    </attribute>
    <attribute>
        <description>
            <![CDATA[This is an <code>exampleAttribute</code>. The default
            value is <code>"exampleDefault"</code>.]]>
        </description>
        <name>exampleAttribute</name>
        <required>true</required>
        <type>java.lang.String</type>
    </attribute>
    <attribute>
        <description>
            <![CDATA[HTML passthrough attribute specifying the
            css style of the element.]]>
        </description>
        <name>style</name>
        <required>false</required>
        <type><![CDATA[java.lang.String]]></type>
    </attribute>
    <attribute>
        <description>
            <![CDATA[List of CSS class names (separated by spaces) that are
            to be rendered within the class attribute.]]>
        </description>
        <name>styleClass</name>
        <required>false</required>
        <type><![CDATA[java.lang.String]]></type>
    </attribute>
    </tag-extension>
        <vdldoc:since>2.0</vdldoc:since>
    </tag-extension>
</tag>

The tags.xml entry and generated taglib.xml declaration are nearly identical. However, thanks to the generator, several elements appear in the taglib.xml entry which are not in the tags.xml file. The generator writes the <component> element and its children, the exampleAttribute's <required> element, and information about default values in the attribute descriptions (look closely at the <description> of exampleAttribute in both files). However, the most helpful elements generated are the additional <attribute> elements. The component developer can specify tags in the <extends-tags> element, and the generator will apply the extended tags' attributes to the current component. This feature eliminates the need for duplicate attribute declarations which occur in normal taglib.xml files.

Generated Java

The generator produces much of the Java code required for creating JSF custom components including attribute getters and setters and rendering code for AlloyUI attributes.

For JSF, each attribute must have a valid Java Bean getter and setter, so the generator creates these getters and setters in the ComponentBase.java file. Take for example, the following declaration of alloy:inputDates panes attribute:

<attribute>
    <attribute-extension>
        <alloy-ui>true</alloy-ui>
    </attribute-extension>
    <description>
        <![CDATA[The number of month panes shown in the popup calendar.
        Valid values are <code>1</code> (the default), <code>2</code>,
        and <code>3</code>.]]>
    </description>
    <name>panes</name>
    <type><![CDATA[java.lang.Integer]]></type>
</attribute>

The above attribute declaration will cause the generator to create the following getter and setter in InputDateBase.java:

public Integer getPanes() {
    return (Integer) getStateHelper().eval(InputDatePropertyKeys.panes,
        null);
}

public void setPanes(Integer panes) {
    getStateHelper().put(InputDatePropertyKeys.panes, panes);
}

Similarly, since the panes attribute simply passes its value through to the client-side AlloyUI JavaScript object, we set the <alloy-ui> element to true. Because this is an AlloyUI attribute, the generator writes helpful rendering code in the ComponentRenderBase.java class. In the case of the panes attribute, the generator writes the following rendering code for us in the InputDateRendererBase.java file:

protected static final String PANES = "panes";

/* ... */

@Override
public void encodeAlloyAttributes(FacesContext facesContext,
    ResponseWriter responseWriter, UIComponent uiComponent) throws
    IOException {

/* ... */

    Integer panes = inputDate.getPanes();

    if (panes != null) {

        encodePanes(responseWriter, inputDate, panes, first);
        first = false;
    }

/* ... */

}

/* ... */

protected void encodePanes(ResponseWriter responseWriter,
    InputDate inputDate, Integer panes, boolean first) throws IOException {

    encodeInteger(responseWriter, PANES, panes, first);
}

The Liferay Faces Generator has helped the Liferay Faces Team to more rapidly develop JSF custom components. Because the generator produces the tedious and boilerplate aspects of JSF components, we can focus on the more challenging, interesting, and important facets of component development. Although I've highlighted the major features of the generator's taglib.xml generation, getter and setter generation, and rendering code generation, the generator produces other helpful code as well. The Generator's wiki page is a great place to get information on all of the generator's features and see examples of the generator's usage.

Finally, the generator is currently designed with only the Liferay Faces project in mind, but I would love to make it more generic. If the you are interested, send me a pull request.

New Liferay Faces Release - Alloy Input Components

Technical Blogs May 7, 2015 By Kyle Joseph Stiemann Staff

New Liferay Faces Release - Alloy Input Components

Juan and Vernon have already blogged about many exciting portal components and the amazing alloy:accordion component, so I want shine a spotlight an a few new and useful Alloy input components: alloy:inputDate, alloy:inputTime, and alloy:autoComplete.

alloy:inputDate and alloy:inputTime

alloy:inputDate and alloy:inputTime were incredibly difficult components to create because of the nature of Java Dates and timezones. However, our pain is your gain, because these components will help you avoid dealing with the rough edges of Java Dates and TimeZones.

alloy:inputDate

alloy:inputDate is a combination of the JSF h:inputText (or HtmlInputText) and AlloyUI's datePicker. Because alloy:inputDate is an h:inputText, it incorporates all the features of h:inputText, but it includes many additional features for validating, submitting, and selecting dates. alloy:inputDate features built-in validation of date Strings and Java Dates (with minDate and maxDate attributes), a built-in f:convertDateTime (or DateTimeConverter), and a clickable pop-up calendar for date selection. Because the pop-up calendar is an AlloyUI Datepicker, it integrates perfectly with the Liferay theme:

alloy:inputDate liferay-ui:input-date

Similarly, alloy:inputDate will automatically use the locale set by Liferay Portal (but you can specify a different locale if necessary). Lastly, alloy:inputDate can be be triggered by input focus, button click, or both.

alloy:inputTime

Similar to alloy:inputDate, alloy:inputTime is an AlloyUI Timepicker attached to an h:inputText. So, it has many features similar to alloy:inputDate: localization, built-in conversion, multiple triggers, minTime/maxTime validation, theme integration, and a pop-up for selecting times. The main difference between alloy:inputDate and alloy:inputTime is that alloy:inputTime can also complete your typed results with a client-side filter.

alloy:autoComplete

alloy:autoComplete is a full-featured auto-complete component which has client-side filtering, server-side filtering, delayed filtering, completion item highlighting, and f:selectItem(s) integration. One other feature of alloy:autoComplete which sets it apart from the competition is the built-in preset filtering. Including phraseMatch, charMatch, startsWith, subWordMatch, and wordMatch, the predefined filters work as either the server or client filters, so if you were planning on using a common filtering mechanism (such as phraseMatch), you can rely on the built-in filter and avoid writing it yourself.

These components are not yet production ready, but they are available for testing via the Liferay Faces Alloy 4.2 beta and the Liferay Faces Showcase. Also of note, all Liferay Faces Alloy components are tested to work in both webapp and portlet environments, so JSF webapp developers can take advantage of them as well.

The Benefits of Answering Forum Posts

General Blogs January 14, 2015 By Kyle Joseph Stiemann Staff

On the Liferay Faces Team, we try to reply to as many posts in the Liferay Faces forums as we can. This has been extremely beneficial for our team and our project. If you're a developer, I want to encourage you to get involved in similar ways in your community by listing some of the benefits the Liferay Faces team has recieved because of our involvment in our forums:

These are some of the main benefits the Liferay Faces Team has seen from our participation in our forums. If you're a developer, I highly recommend that you get similarly involved in your community and see if it doesn't help improve you, your project, and your community.

Remote Debugging Liferay in NetBeans 8

Technical Blogs October 16, 2014 By Kyle Joseph Stiemann Staff

Currently, Liferay has excellent Eclipse support with the Liferay IDE and Liferay Developer Studio. However, as of this writing, Liferay has no official NetBeans plugins or IDE. So what are you to do if you want to develop on Liferay in NetBeans? Well you can run Liferay from the terminal of course, but what if you want to debug your code or Liferay's code or both? Remote debugging is the solution. Here's how you can do it with NetBeans:

  1. Load up the source code for your project and (optionally) the source code for Liferay Portal in Netbeans.
  2. Compile your project in debug mode.
  3. Set your breakpoints.
  4. In the terminal go into Tomcat's bin/ directory:
    $ cd $LIFERAY_HOME/tomcat-${version}/bin
  5. Execute the following command to start up Tomcat in debug mode:
    $ ./catalina.sh jpda start
  6. Once the portal has started, deploy your project to Liferay.
  7. In NetBeans attach a debugger to the running Tomcat by selecting Debug -> Attach Debugger... from the menu bar.
  8. In the Attach Debugger... dialog (assuming that you are using the default Tomcat settings) set the port to 8000 and click OK.

After that, the NetBeans debugger should connect to the running Tomcat and allow you to debug Liferay.

Thanks to Alex Wallace for his forum post explaining how to do this.

Showing 12 results.
Items 20
of 1