So a few days ago I run into a bug that took me almost a whole day to sort out..
I usually use cargo when I want to deploy an app to a running container but today I've spent several hours trying to make my app redeploy on a remote glassfish web profile server while working within my development/integration environment.
Just to give you some context in this environment I needed to continually deploy the same application on the same server but with different versions.
The first time I deployed the application everything will work as expected but subsequent deployments will throw an error telling me that an application already exists for that context root (see message below) :
Caused by: org.codehaus.cargo.util.CargoException: Deployment has failed: Action failed Deploying application to target server failed; Error occurred during deployment: Application with name myapp-1.4.8 is already registered. Either specify that redeployment must be forced, or redeploy the application. Or if this is a new deployment, pick a different name. Please see server.log for more details.
Now the asadmin utility tool allows forcing a redeployment by using the --force=true option on the command line but it doesn't work if the WAR file name has changed as glassfish supports only one app per context root unless you use it in conjunction with Glassfish application versioning system but more on that later (see here)
I would argue that the "--force" param should deploy the WAR for a given context and overwrite the existing app regardless if you are using the versioning system or not but that's only my point of view
So now let's get down to business, in this tutorial I will be showing how to use the codehaus maven exec plugin
Below are the steps that you should follow :
0.- Prerequisites
a. Glassfish versionning system naming conventions
Before beginning with this tutorial you must know that in order for it to work you need to use glassfish's versionning system with your applications otherwise it will always fail when trying to deploy an app for a given context but with a different war name (e.g. myapp-1.0.war -> myapp-1.1.war)
You can find more info on the versionning system here and here but basically glassfish will handle multiple versions of your application for a given context but allowing only 1 version of the application to be active at a given moment
For the versioning system to work you need to define a version for your WAR either in the glassfish-web.xml file or with the -name argument
In this tutorial we will be using the latest (the --name) argument
Please note that you need to respect a WAR file naming convention when versioning your applications (the value for the --name parameter), that convention is :
{applicationName}:{applicationVersion}.war --> myapp:1.0.war
b. Access rights to Glassfish install path
You will also need to install(unzip) a glassfish instance in a place accessible to the the machine that will be executing the maven goal
c. Enabling asadmin secure admin feature
Lastly Glassfish's secure admin feature needs to be enabled in order to be allowed to do remote deploys; otherwise you will get an error message
[exec] HTTP connection failed with code 403, message
You can enable the secure admin feature by running the following command on your prompt (glassfish instance must be running)
asadmin --host [host] --port [port] enable-secure-admin
Please note that you have to restart the glassfish instance in order for this functionality to be enabled.
1.- Installing a local glassfish instance
Go to the glassfish download website and download and unzip the appropriate glassfish version (ideally the same that the one of the remote server where you are trying to deploy your app) in a directory of your choice : e.g. /var/glassfish
2.- Defining the password file
You will then need to provide the asadmin tool with a password file since it's no longer supported as a command line argument
So go ahead and create a password file (let's name it glassfish.password) in the folder of your chice (e.g. /var/glassfish/). The file should be a properties files containing the following keys with the passwords values corresponding to your environment:
AS_ADMIN_MASTERPASSWORD=myPassword AS_ADMIN_PASSWORD=myPassword AS_ADMIN_USERPASSWORD=myPassword
3.- Configuring the exec plugin
Head up to your pom.xml file fire up your favorite editor and edit the POM file so it looks something like :
... .... /var/glassfish/bin/asadmin admin /var/glassfish/glassfish.password arte-epg-apipreprod.sdv.fr myapp ... org.codehaus.mojo exec-maven-plugin 1.2.1 ${glassfish.asadmin.executable} --user ${glassfish.user} --passwordfile ${glassfish.password.file} --host ${glassfish.remote.host} deploy --force=true --name=${project.build.finalName}:${project.version} --enabled=true ${project.build.directory}/${project.build.finalName}.war exec verify
Please ensure that the value of the --name argument respects glassfish's application versioning naming conventions {appName}:{appVersion}.war
mvn clean verify
4.- Sum-up and final thoughts
Firstly let me tell you that this method is probably not the cleanest way to get things done but for the time being, it will suffice... (at least to me :p)
Secondly, this is not a silver bullet, as sometimes I did encounter problems for example : if the database was not up and the application was marked as not enabled in the glassfish server, or the first time that I switched from deploying without glassfish versioning system to using glassfish's versioning system
Finally, I really don't like the fact that I need a local glassfish instance to deploy on a remote server, and I wonder if it's possible to achieve something similar using the glassfish deployment-client as a maven dependency and invoking the java classes inside the dependency or somehow extend the plugin to take into account force redeploys. So if I have some free time in the near future I will explore the possibility of accomplishing the same thing without needing a glassfish installed locally
Can you expand on what you mean by "you need to respect a WAR file naming convention when versioning your applications"
ReplyDeleteHi,
ReplyDeleteYes I'm referring to the value of the '--name' parameter.
If you take a look at the documentation over at Oracle(see the bottom of my response) It is stated that when you want to exploit the versioning feature you will need to provide with a version identifier suffix that will append to your application name separated by a colon (:).
So when deploying an application to a glassfish server using the versioning feature you will need to provide the mandatory '--name' parameter with a value that respects that naming convention (i.e. appName:version).
Here is an exemple on how a asadmin command would look like with the different params
asadmin deploy --host localhost --user=admin --passwordfile=mypasswordFile.txt deploy --name=myApp:1.0 --force=true --enabled=true myapp.war
Hope that helps
oracle docs : http://docs.oracle.com/cd/E18930_01/html/821-2417/gihzx.html#gkhhv
Hi Ulises.
ReplyDeleteThis is a great tutorial! I would like to suggest a few things though.
When I first tried this out, I was not able to run it successfully. I was having the following errors:
[exec] HTTP connection failed with code 403, message: Forbidden
[exec] Command deploy failed.
After google-ing things up, I found out that the domain where I am trying to deploy on my remote glassfish instance should have been "enable-secure-admin".
Maybe you could add such information on your blog so newbies like me would know the prerequisites on deploying applications to remote glassfish instances?
This could, maybe, be just one of the set-ups needed and some other more are there which we do not know of.
This was a great tutorial!
Cheers!
~Michael
Hi Michael,
DeleteThanks for the comment, you are right I should have pointed out that you need to have the "secure admin" feature enabled in order to be able to deploy remotely on a glassfish instance.
I will edit the tutorial and add this for future reference, thanks for pointing it out.
Cheers
Ulises