Saturday, 18 April 2015

Interactions with RichTree

Possible cases

Interacting with the tree may have many faces. You e.g. might need to:

- react to clicking on tree nodes,
- traversing the tree by expanding nodes,
- selecting / multiselecting tree nodes.

Also you might need to change the tree state by invoking external actions, e.g. clicking the external button to:

- expand relevant tree path,
- change tree's selection.


Working example ilustrating the use case

Let's think of following application (run example). I provide functionality of traversing the tree with two external buttons (it's a wizard like navigation - Next - Previous - relation). I also provide expansion of tree node by clicking a button (I've hard-coded 'Web containers' node to be expanded).

How does it work

To implement the tree I used Java Server Faces 2.1 web MVC with RichFaces 4.5.4 <rich:tree> component. On the xhtml side I configured it in the following way:

<rich:tree id="tree"
    selectionType="ajax"
    value="#{webTechnologiesTreeBean.rootNode}"
    var="node" 
    selection="#{webTechnologiesTreeBean.selection}"
    selectionChangeListener="#{webTechnologiesTreeBean.processTreeSelectionChange}">
    <rich:treeNode expanded="#{node.expanded}" iconLeaf="images/mobilne.jpg">
        <h:outputText value="#{node.data.name}"/>
    </rich:treeNode>
</rich:tree>
On the managed bean side i've bound component properties in the following way (selection to WebTechnologiesTreeBean) :


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
 @ManagedBean
 @SessionScoped
 public class WebTechnologiesTreeBean implements Serializable, ITree {

     private Collection<Object> selection = new ArrayList<Object>()

     @Override
     public Collection<Object> getSelection() {
         return selection;
     }

     public void setSelection(Collection<Object> selection) {
         this.selection = selection;
     }

     (..)

 }   

... and expansion to WebTechnologiesTreeNode class:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
 public class WebTechnologiesTreeNode extends TreeNodeImpl implements Serializable{

     private boolean expanded = false;
    
     public boolean isExpanded() {
         return expanded;
     }

     public void setExpanded(boolean expanded) {
         this.expanded = expanded;
     }

     (..)
 }

The whole tree model has been built using Builder design pattern implemented inside WebTechnologiesTreeNode. This building process includes passing data to nodes and node keys which are node's indentifiers within a tree. Leaf node's keys are auto-numerated with "1", "2" etc.. Using this String typed keys i am able to retrieve relevant node later on.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
private WebTechnologiesTreeNode createRootNode() {
    WebTechnologiesTreeNode result = new WebTechnologiesTreeNode.NodeBuilder().build();
    WebTechnologiesTreeNode frameworkNode = new WebTechnologiesTreeNode.NodeBuilder()
            .withData(new SimpleNodeData("Web frameworks"))
            .withChildLeaf(new WebLinkNodeData("Java server faces", "https://javaserverfaces.java.net/"))
            .withChildLeaf(new WebLinkNodeData("Vaadin", "https://vaadin.com/home"))
            .withChildLeaf(new WebLinkNodeData("Spring MVC", "http://projects.spring.io/spring-framework/"))
            .withChildLeaf(new WebLinkNodeData("Play", "https://www.playframework.com/"))
            .withChildLeaf(new WebLinkNodeData("Struts", "https://struts.apache.org/"))
            .build();
    WebTechnologiesTreeNode containerNode = new WebTechnologiesTreeNode.NodeBuilder()
            .withData(new SimpleNodeData("Web containers"))
            .withChildLeaf(new WebLinkNodeData("Tomcat", "http://tomcat.apache.org/"))
            .withChildLeaf(new WebLinkNodeData("Glassfish", "https://glassfish.java.net/"))
            .withChildLeaf(new WebLinkNodeData("JBoss", "http://www.jboss.org/"))
            .build();
    result.addChild("frameworks", frameworkNode);
    result.addChild("containers", containerNode);
    return result;
}

Handling expansion programatically (server-side)

Now, when I've got data model, property bindings I can collapse / expand my hard-coded node with key 'containers' (display name 'Web containers').

1
2
3
4
5
 public void switchContainersExpansion() {
     WebTechnologiesTreeNode node = 
         (WebTechnologiesTreeNode) rootNode.getChild("containers");
     node.setExpanded(!node.isExpanded());
 }

Handling selection on server side

In RichFaces 4.5.X selection is kept with List<SequenceRowKey> each SequenceRowKey instance has a path consisted of tree node string keys. For example, in my demo app, path to 'Java Server Faces' tree node would be SequenceRowKey["frameworks", "0"], path to 'JBoss' node would be SequenceRowKey["containers", "2"]

To programatically set single selection on <rich:tree> I have to set one element list in bound selection property. Let's say I want to set 'JBoss' selected:
1
2
3
 Collection<Object> mySelection = new ArrayList();
 mySelection.add(new SequenceRowKey("containers", "2"));
 treeBean.setSelection(mySelection);
Please feel free to review source code of my example application and see GitHub repository.

Thursday, 9 April 2015

Page refresh and file download in a single breath

Functional requirement

Let's say we are supposed to display some data on page before downloading a file in web application. Think of displaying number of downloads or last time the file has been downloaded. Yes, that's a piece of cake, you may say dear reader. 

Almost a solution

I can write a Servlet that generates HttpResponse with relevant Content-Type, Content-Disposition in the header and my file's stream. Actually it would work. But what about refreshing page.

As we know there can be only one response per request. So where to put refreshed page content? 

Two ways of downloading files

I've implemented following examples:

1° Not perfect but whole navigation is enclosed within single page.
2° Perfect but additional browser window is beeing opened.



Implemented example: Single page case

Please play a little bit with working example to check how things work. You may analyse conversation with web server in your browser by debugging (F12).

You may notice that in single page case, refreshing page (F5) in browser causes downloading file once again without setting last download time. That's because browser refresh (F5) causes repeating of the last request (which is in our case request for the file).

To understand case 1° trick look at following snippet:

    <c:if test="#{onSamePageDownloadBean.readyForDownload}">        
      <script type="text/javascript">
        window.onload = function() {
          document.getElementById('downloadForm:downloadFile').click();
        }
      </script>
    </c:if>
After clicking Download button, the same page is rendered once again but with flag readyForDownload = true passed (in request). In this case on page load JavaScript triggers the server download file action by clicking hidden button in form on the same page:


    <h:form id="downloadForm">
        <h:commandButton id="downloadFile" 
                         action="#{onSamePageDownloadBean.download()}" 
                         style="display:none"/>
        <h:commandButton id="redirectAndDownload" 
                         action="#{onSamePageDownloadBean.redirectWithDownload()}" 
                         value="Download file"/>
        <h:commandButton id="back" 
                         action="index.html?faces-redirect=true" 
                         value="Back"/>
    </h:form>


Implemented example: New browser window case 

Case 2° has no tricks, it just sends two requests - first updating page, and the second with JavaScript demanding to open new window with the downloadWindow URL:

    <h:form id="downloadForm">        
      <h:commandButton id="openWindowAndDownload"
                       action="#{openWindowDownloadBean.update()}"
                       onclick="window.open('downloadWindow.xhtml');"
                       value="Download file"/>
    </h:form>

To review the two aforementioned examples see complete sources on GitHub.

Sunday, 29 March 2015

Profiler for web applications

Is your Application intended to run faster, any memory issues, redundant referring to database? Need a profiler for your web application?

The producer of famous JRebel tool - ZeroTurnaround has released new 2.0 Beta version of live profiler for Java EE apps which is a remedy for the majority of significant bugs. Profiler is able to analyse session object and alert user when it rapidly increases with comprehensive UI in web browser. With XRebel you can finesse your app by instantly receiving information about thrown Exceptions or database queries with their duration.

More info: ZeroTurnaround's site.

Publish your online application for free

You've got a Java Enterprise, Ruby, Node.js application and would like to deploy making it available in public? You'd like your client, boss, friends to see the progress of your work?
Give yourself 30 minutes and configure stunning free hosting platform.

Prerequisites

You are able to host up to 3 web applications in the RedHat cloud for free. They give you no time limits, expiring trial. Registering with a valid e-mail will be sufficient.

How does it work?

OpenShift - the aforementioned platform is based on Git. After creating an application with web interface and following some instructions from quick start guide, you are allowed to clone remote Git repository and add your own code or add ready to deploy artifacts built locally.
Next you commit changes back to repository and magic happens. You application is accessible all over the world to everyone.

Continuous Integration

Platform gives you the tools you need to manage entire development lifecycle by integrating Jenkins. After clicking 'Enable Jenkins' you will enable your applications to execute complex builds every time you push code (and additionally execute your unit tests).

Application Integration

To connect your applications, services and data you may want to use an ESB. JBoss Fuse for xPaaS is an enterprise service bus technology for building and implementing communication in a broad sense. It makes it possible to connect applications using notifications and messages.

To sum up...
The installation process is simple, you just need to have ruby, git installed and follow instructions from guide step by step.

Have fun with your new cloud platform.

Thursday, 26 March 2015

Multi-module Java EE web application

The subject of the application is simple examination tool. User can configure answers to questions 'Administrate answers' and then 'Take an exam'.

Run the example application: http://examstarter-phojnacki.rhcloud.com/

To implement a starter example I've chosen:

  - Java,
  - EJB,
  - JBoss,
  - Maven,
  - Struts 2 (+Conventions Plugin)




I divided an application into following modules

- exam-business-logic-api - interfaces on which depend ejb and web modules,
- exam-business-logic - ejb module with business logic implementation,
- exam-business-logic-ear - ear with business logic (intentionally deployed separately to test remote communication - in JBoss 7 each deployment unit classes are loaded using different Class Loader),
- exam-web - web application based on Struts 2 framework (whole configured with Conventions Plugin), also deployed separately as war.



Application has been implemented using Struts2 MVC framework . I configured actions with annotations solely (dependency on Struts 2 Conventions Plugin). I also followed Post-Redirect-Get web design pattern.

You can configure exam questions in business logic module:

@Stateless(mappedName = "ExamQuestionsService")
@Remote(ExamQuestionsService.class)
public class ExamQuestionsServiceBean implements ExamQuestionsService {
 
    @Override
    public List<ExamQuestion> getExamQuestions() {
        ExamQuestion examQuestion1 = new ExamQuestion();
        examQuestion1.setQuestion("What is the current version of Struts?");
        examQuestion1.setAnswer("2.3.20");
        ExamQuestion examQuestion2 = new ExamQuestion();
        examQuestion2.setQuestion("How many principles are in S.O.L.I.D.?");
        examQuestion2.setAnswer("5");
        ExamQuestion examQuestion3 = new ExamQuestion();
        examQuestion3.setQuestion("Software design pattern in which an (..)");
        examQuestion3.setAnswer("Observer");
 
        List result = new ArrayList();
        result.add(examQuestion1);
        result.add(examQuestion2);
        result.add(examQuestion3);
 
        return result;
    }
 
}

To review or clone an example please visit my exam GitHub repository. Instructions of building and deploying are attached in README file.

 GitHub repository of this starter application

I've deployed ear and war artifacts on RedHat OpenShift (examstarter application).

Saturday, 21 March 2015

Interview with Robert C. Martin on SOLID principles.

Five SOLID principles give guidelines on how to organize code into classes:

Single responsibility,
Open-close,
Liskov substitution,
Interface segregation,
Dependency inversion.

Robert Martin is a developer, acclaimed speaker at conferences worldwide, and the author of many books including: The Clean Coder, Clean Code, Agile Software Development: Principles, Patterns, and Practices, and UML for Java Programmers.

Interview gives a picture on how to think while designing software using SOLID.