Sunday 29 March 2015

Advanced File download with PrimeFaces

Introduction


When your Web application needs to send a file to the browser, the classic approach is using a web servlet to serve the contents.
PrimeFaces has a specific tag for downloading a file, so that you don't need a servlet. And with a small trick, you can even update the screen in the same action.

FileDownload component

The example with the servlet can be skipped, I guess. Everyone created already a servlet which is able to send content to the browser.
When you are working with JSF, and PrimeFaces, there is an alternative for the servlet approach.
PrimeFaces has the FileDownload component. It is an ActionListener, so you can use it on a commandButton to perform the download.

Let's have an example.
<p:commandButton value="Download" ajax="false">
    <p:fileDownload value="#{fileBean.file}"/>
</p:commandButton>

@ManagedBean(name = "fileBean")
@RequestScoped
public class FileDownloadController {

    public StreamedContent getFile() {
        InputStream stream = this.getClass().getResourceAsStream("/yourfile.txt");        return new DefaultStreamedContent(stream, "text/plain", "downloaded_file.txt");    }
    
}

The StreamedContent, already used by the graphicImage component, contains the data which is send to the browser. You can supply the constructor with an InputStream which has the actual contents.

This can be static file or a dynamically generated one. The PrimeFaces code is then responsible for reading from the InputStream and send it to the browser. Together with the required housekeeping like setting the mime type, http status and setting the JSF response as completed.

Advanced use case

Together with file download, there are use cases where you also need to update the screen which initiated the download.
Recently we had the use case where the end user can specify some options of the file he wants to download.  The options are presented in a dialog which should be preferably closed when the download is performed. Also the screen should be indicate the file download occurred.

Here the RemoteCommand is the solution to these cases.  The RemoteCommand allows to call some JSF bean methods and JSF lifecycle methods from JavaScript.

<p:commandButton value="Download2" ajax="false" onclick="pageRefresh();">
    <p:fileDownload value="#{fileBean.file}"/>
</p:commandButton>
<p:remoteCommand update="@all" name="pageRefresh"/>

When we click on the button, the onClick activates the javaScript version of the RemoteCommand and initiates a AJAX partial page refresh of the screen. On the other hand, the click on the button also initiates the ActionListener of the FileDownload component to perform the file download.

Since we where able to initiate 2 calls, we can perform 2 actions, the download and the screen update.

Conclusion

With the help of the FileDownload component it becomes easier to program the download of a static or dynamic file in JSF. You no longer need a servlet to perform these kind of actions.
With the help of the very broad useable RemoteCommand component, we can even initiate 2 actions.  The file download and some screen updates.


Sunday 15 March 2015

Override Java settings on OpenShift

Introduction


With OpenShift, your server instance in the cloud is prepared with a few mouse clicks or with a single command with the rhc tool.
In most of the cases, this is all you need and you can start right away with your freshly created server instance (named gear in OpenShift terminology).
But in other situations, you want to make some changes to the Java environment, like setting system properties or changing the security settings.

In the case of the security settings, in a normal environment, you can update the java.security file in the JRE_HOME/lib/security folder.  But on the OpenShift environment there are some constraints which makes this task a bit more difficult.  This text shows you an easy way to accomplish your goal.

History

We have developed a JSF application which uses OAuth2 as authentication means.  So we are using an SSL connection to the OAuth2 provider to verify the tokens which are presented to the applications.
It was working fine on OpenShift with the latest WildFly 8.2 cartridge. And last week, we created a new gear and our application throw an exception

java.security.NoSuchAlgorithmException: EC AlgorithmParameters not available

When we compared this new instance with the instance we had already running, we found out that the java version was different.  The newest one, is using OpenJDK 8u31.  And searching on the web for the combination of this version and the exception we received, revealed that there is an issue with this version related to Elliptic curve algorithm.

So, the next step was to edit the java.security file to exclude the algorithm which causes problems in our cases.  
The key jdk.tls.disabledAlgorithms in the file, needs to contain the codes of the algorithms we don't want, in our situation EC,ECDHE,ECDH.

But when I opened the java.security file and wanted to change the content, I received the warning that the film is read-only.  And you can't change it and you can't become a super user to overrule it.

And I can understand that you want to secure some parts of the server.  But it is no option for us to rewrite the Web application with Java 7 due to a, hopefully, temporarily issue with the Java which is running on the gear.

Solution

The solution was found when I found the blog of Eyal Lupu which gives a nice example of how you can override the contents of the java.security file (the documentation in the file itself indicate already this possibility but with the example it became clear for me) and the OpenShift user guide.

So we created a file on the gear to override the key jdk.tls.disabledAlgorithms from the java.security file. And by setting a system property using the JAVA_OPTS_EXT environment variable of the gear, we are able to make the application run again without throwing the exception.

Create the file

  •  rhc ssc gearName
  •  cd $OPENSHIFT_DATA_DIR
  •  vi override_security.properties
  •  content is jdk.tls.disabledAlgorithms=EC,ECDHE,ECDH
  •  pwd -> and note down (copy) the full path location of the just created file.
  •  exit

Set the environment variable

  •  rhc env set JAVA_OPTS_EXT=-Djava.security.properties=file:<> -a gearName
Restart your gear/app

  •  rhc app restart -a gearName


The OPENSHIFT_DATA_DIR isn't chosen at random.  It is the only directory which isn't cleared when you push some code to the git repository. So our file is save there and will not be touched by any of the system processes.

Conclusion

The JAVA_OPTS_EXT environment variable is important if you want to change some settings of the Java Environment.  You can add some system properties to configure your application (like setting the JSF project stage) or to override the java.security configuration for instance as explained in this text.


Hope this help you if you have a similar 'issue' with OpenShift.