But JWS does not realize its original intention successfully. From several great revisions of Java we can see that JWS has many bugs and flaws, so Sun and Oracle have to frequently put patches to fix them. You can see that how many big or small upgrades in Java 5 and 6 are related to Java Web Start. No wonder so many people sighed: “I will not use Java Web Start any longer!”In fact, this is not always the case. With improvement in Java, we are able to eliminate some potential problems in JWS and to apply it successfully to enterprise applications as long as we have the knowledge of more skills.
Taking 2BizBox ERP project as an example, this article will introduce how to use the technology of dynamically generating JNLP file to realize rapid deployment in enterprise applications.
We all know that as a free-charged and quality ERP software, 2BizBox ERP has thousands of users. There are nearly one thousand servers our development team have the responsibility to maintain, not to mention the over a hundred client-sides each enterprises has. There is no doubt that it will be a huge workload if we apply the method to download client-sides to install the program and maintain all of these client-sides. In this way, neither the users nor us development team will feel relaxed and convenient. To solve it, the application of JWS is a must. In order to let the client-sides automatically download and install programs, we have deployed the following JNLP files on enterprises’ 2BizBox ERP servers.
The following JNLP file has defined the jar package needed for starting a 2BixBox ERP client-side and the download location and the jre edition.
<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0+" codebase="http://**.**.**.**/webstart/">
<information>
<title>2BizBox</title>
<vendor>Serva Software</vendor>
<homepage href="http://www.2bizbox.com"/>
<description>2BizBox ERP 3</description>
<offline-allowed/>
</information>
<security>
<all-permissions/>
</security>
<update check="always" policy="always"/>
<resources>
<j2se href="http://java.sun.com/products/autodl/j2se" version="1.6+" initial-heap-size="128m" max-heap-size="512m"/>
<jar href="2bizbox.jar />
<jar href="lib1.jar />
<jar href="lib2.jar />
<jar href="lib3.jar />
<jar href="lib4.jar />
<!-- more jar.... -->
</resources>
<application-desc main-class="com.serva.bb2.gui.Main">
<argument>**.**.**.**</argument>
</application-desc>
</jnlp>
It looks good in actual application. However, because of JNLP and the bugs in JWS itself, in some circumstances, users cannot obtain updates by starting JNLP after renewing and updating background jar programs. They have to clear up JWS cache by force, which, in general, users have not any idea. In another case, when changes have taken place in the jar package of ERP itself (such as addition or deletion of classes in it) which is equivalent to changes in the content in JNLP file, user-sides are asked to be aware of the changes in JNLP and to update JNLP first. In many java editions (for example, early jre6 editions and editions before ure6 update20), JNLP at user-sides cannot be updated successfully because of reasons like potential bugs, hence the failure in starting program.
How to solve this problem? An effective way is to apply the dynamic JNLP.
How to solve this problem? An effective way is to apply the dynamic JNLP.The way of dynamic JNLP: at the background of server, a JNLP file is dynamically generated by jsp or servlet instead of placing a static and unchanging JNLP file. Therefore, through the logic of background application we can dynamically generate or create the content of a JNLP file like what kind of jar archive and which jre edition is needed.
Take jsp as an example. In this jsp, the several key points you need to pay attention to are: first, set this page not to be buffered by the browser in order to avoid jnlp content’s not being able to be updated in time. Second, set mime class and let the browser consider it as a jnlp file in order to be downloaded instead of showing it directly in the browser. These can be realized by setting response.
response.setHeader("Pragma", "no-cache");Meanwhile, the browser and webstart can be set as not allowed to cache content in jnlp by setting response.setHeader(“Pragma”, “no-cache”); and
response.setHeader("Expires", "0");
response.setHeader("Content-Disposition", "filename=\"bb.jnlp\";");
response.setContentType("application/x-java-jnlp-file");
response.setHeader(“Expires”, “0″);. You can also set the type of files and give a dynamic file name through response.setHeader(“Content-Disposition”, “filename=\”bb.jnlp\”;”);response.setContentType(“application/x-java-jnlp-file”);
You need to pay attention to a problem that when dynamically generating jnlp file you must be careful not to set the href tag in jnlp file. Why? You can see the words in jnlp format document:
http://lopica.sourceforge.net/ref.html#jnlp
The jnlp file's one and only root.
Attributes
spec=version , optional
Specifies what versions of the jnlp spec a jnlp file works with. The default value is 1.0+. Thus, you can typically leave it out.
version=version , optional
Specifies the version of the application as well as the version of the jnlp file itself.
codebase=url , optional
Specifies the codebase for the application. Codebase is also used as base URL for all relative URLs in href attributes.
href=url , optional
Contains the location of the jnlp file as a URL. If you leave out the href attribute, Web Start will disable the update check on your JNLP file, and Web Start will not treat each new JNLP file as an application update - only updated jar files will. Leaving out href usually makes only sense if your jnlp file is created dynamically (that is, throug a cgi-script, for example) and if your jnlp file's arguments or properties change from request to request (user to user).
Note, that Java Web Start needs href to list your app in the Web Start Application Manager.
So, when dynamically generating JNLP, don’t set href. In this way the browser will download JNLP file anew at every turn.
Another point is that the jar archive in JNLP file can dynamically check the jar archive in the file and dynamically generate it. Therefore, if there is addition or deletion in the jar files in the program, there will be no need to modify jnlp files. The method is also quite simple: check the absolute path of the current web in the server and list all jar files, then output them when generating jnlp.
Then list them as described in the following code in jar’s part:
<%
String urlString=request.getRequestURL().toString();
URL url=new URL(urlString);
String host=url.getHost();
String path = request.getSession().getServletContext().getRealPath("/");
path=path.replace("\\.\\", "\\");
File file=new File(path);
String[] files = file.list();
ArrayList jarNames=new ArrayList();
for(int i=0;i<files.length;i++){
String fileName=files[i];
if(fileName.toLowerCase().endsWith(".jar")){
jarNames.add(fileName);
}
}
%>
<resources>At last, if it is necessary to specify the ip address or the host address of the current server in jnlp, it can also be done by dynamic generation, such as the codebase in jnlp file. In addition, the ip address of the current server must also be given in the main function in 2BizBox ERP. However, it is out of our imagination, if every jnlp in over a thousand 2BizBox servers needs to be maintained manually. Now this problem can be perfectly solved by means of dynamic generation.
<j2se href="http://java.sun.com/products/autodl/j2se" version="1.6+" initial-heap-size="128m" max-heap-size="512m"/>
<%
for(int i=0;i<jarNames.size();i++){
out.write("\n");
out.write("<jar href=\""+jarNames.get(i).toString()+"\"/>");
}
%>
</resources>
String urlString=request.getRequestURL().toString();Then in jnlp:
URL url=new URL(urlString);
String host=url.getHost();
<jnlp spec="1.0+" codebase="http://<%=host%>/webstart/">The method to dynamically generate jnlp through jsp is thus completed. It goes well in 2BizBox ERP and let over a thousand 2BizBox ERP cloud-host users quickly get their programs updated and simplify the maintaining of programs.
...
<application-desc main-class="com.serva.bb2.gui.Main">
<argument><%=host%></argument>
</application-desc>
This is a nice explaination, but I wonder how you are dealing with Java 1.7.51's signature requirements. I would like to put the jnlp within the signed jar file using APPLICATION_TEMPLATE.JNLP, but I'm not sure this is possible with dynamic jnlp.
ReplyDelete