tarka
tarka

Reputation: 5607

Deploy Application on Glassfish3+ programmatically

I have a use case that requires me to control the deployment (amongst other things) of an application on a Glassfish server from within an application.

Is it possible to use one application on a glassfish server to deploy and control other applications on the same glassfish server?

Upvotes: 2

Views: 950

Answers (3)

A J Qarshi
A J Qarshi

Reputation: 2992

I believe basic Glassfish server administration can be handled using JSR88 APIs. Though these APIs are marked optional in Java EE 7 but they work. I think you can use these APIs in both Java SE and EE applications.

There are wrapper APIs available here which you can be used to manipulate all major Java EE containers. These APIs also use JSR88.

There is a sample code available here to deploy/undeploy a Java EE application. This sample works with some older version of Glassfish (Glassfish2x probably).

I have modified the sample code a little bit to make it work with Glassfish4x which I am posting here:

package simplewardeployer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.deploy.shared.ModuleType;
import javax.enterprise.deploy.shared.factories.DeploymentFactoryManager;
import javax.enterprise.deploy.spi.DeploymentManager;
import javax.enterprise.deploy.spi.TargetModuleID;
import javax.enterprise.deploy.spi.exceptions.DeploymentManagerCreationException;
import javax.enterprise.deploy.spi.exceptions.TargetException;
import javax.enterprise.deploy.spi.factories.DeploymentFactory;
import javax.enterprise.deploy.spi.status.ProgressEvent;
import javax.enterprise.deploy.spi.status.ProgressListener;
import javax.enterprise.deploy.spi.status.ProgressObject;


public class Main {

class DeploymentListener implements ProgressListener {

    Main driver;

    String warContext;

    DeploymentListener(Main driver, String warContext) {

        this.driver = driver;

        this.warContext = warContext;

    }

    public void handleProgressEvent(ProgressEvent event) {

        System.out.println(event.getDeploymentStatus().getMessage());

        if (event.getDeploymentStatus().isCompleted()) {

            try {

                TargetModuleID[] ids = getDeploymentManager().getNonRunningModules(ModuleType.WAR, getDeploymentManager().getTargets());

                TargetModuleID[] myIDs = new TargetModuleID[1];

                for (TargetModuleID id : ids) {

                    if (warContext.equals(id.getModuleID())) {

                        myIDs[0] = id;

                        ProgressObject startProgress = driver.getDeploymentManager().start(myIDs);

                        startProgress.addProgressListener(new ProgressListener() {

                            public void handleProgressEvent(ProgressEvent event) {

                                System.out.println(event.getDeploymentStatus().getMessage());

                                if (event.getDeploymentStatus().isCompleted()) {
                                    driver.setAppStarted(true);

                                }

                            }

                        });

                    }

                }

            } catch (IllegalStateException ex) {

                ex.printStackTrace();

            } catch (TargetException ex) {

                ex.printStackTrace();

            }

        }

    }

}

DeploymentManager deploymentManager;

boolean appStarted;

boolean appUndeployed;

String warContext;

String warFilename;

String wsdlUrl;

synchronized void setAppStarted(boolean appStarted) {

    this.appStarted = appStarted;

    notifyAll();

}

synchronized void setAppUndeployed(boolean appUndeployed) {

    this.appUndeployed = appUndeployed;

    notifyAll();

}

private String getParam(String param) {

    return (null == deploymentProperties) ? null : deploymentProperties.getProperty(param);

}

public DeploymentManager getDeploymentManager() {

    if (null == deploymentManager) {

        DeploymentFactoryManager dfm = DeploymentFactoryManager.getInstance();

        try {

            Class dfClass = Class.forName(getParam("jsr88.df.classname"));

            DeploymentFactory dfInstance;

            dfInstance = (DeploymentFactory) dfClass.newInstance();

            dfm.registerDeploymentFactory(dfInstance);

        } catch (ClassNotFoundException ex) {

            ex.printStackTrace();

        } catch (IllegalAccessException ex) {

            ex.printStackTrace();

        } catch (InstantiationException ex) {

            ex.printStackTrace();

        }

        try {

            deploymentManager
                    = dfm.getDeploymentManager(
                            getParam("jsr88.dm.id"), getParam("jsr88.dm.user"), getParam("jsr88.dm.passwd"));

        } catch (DeploymentManagerCreationException ex) {

            ex.printStackTrace();

        }

    }

    return deploymentManager;

}

TargetModuleID getDeployedModuleId(String warContext) {       
    TargetModuleID foundId= null;
    TargetModuleID[] ids = null;
    try {
        ids = getDeploymentManager().getAvailableModules(ModuleType.WAR, getDeploymentManager().getTargets());
        for (TargetModuleID id : ids) {
            if (warContext.equals(id.getModuleID())) {
                foundId = id;
                break;
            }
        }
    } catch (TargetException | IllegalStateException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    }

    return foundId;
}

void runApp(String warFilename, String warContext) {

    setAppStarted(false);
    ProgressObject deplProgress;
    TargetModuleID foundId = getDeployedModuleId(warContext);
    if (foundId != null) {
        TargetModuleID[] myIDs = new TargetModuleID[1];
        myIDs[0] = foundId;
        deplProgress = getDeploymentManager().redeploy(myIDs, new File(warFilename), null);
    } else {
        deplProgress = getDeploymentManager().distribute(getDeploymentManager().getTargets(),
                new File(warFilename), null);
    }
    if (deplProgress != null) {
        deplProgress.addProgressListener(new DeploymentListener(this, warContext));
        waitForAppStart();
    }

}

void undeployApp(String warContext) {

    setAppUndeployed(false);

    try {

        TargetModuleID[] ids = getDeploymentManager().getRunningModules(ModuleType.WAR, getDeploymentManager().getTargets());

        TargetModuleID[] myIDs = new TargetModuleID[1];

        for (TargetModuleID id : ids) {

            if (warContext.equals(id.getModuleID())) {

                myIDs[0] = id;

                ProgressObject startProgress = getDeploymentManager().undeploy(myIDs);

                startProgress.addProgressListener(new ProgressListener() {

                    public void handleProgressEvent(ProgressEvent event) {

                        System.out.println(event.getDeploymentStatus().getMessage());

                        if (event.getDeploymentStatus().isCompleted()) {

                            setAppUndeployed(true);

                        }

                    }

                });

            }

        }

    } catch (IllegalStateException ex) {

        ex.printStackTrace();

    } catch (TargetException ex) {

        ex.printStackTrace();

    }

    waitForAppUndeployment();

}

void releaseDeploymentManager() {

    if (null != deploymentManager) {

        deploymentManager.release();

    }

}

synchronized void waitForAppStart() {

    while (!appStarted) {

        try {

            wait();

        } catch (InterruptedException e) {
        }

    }

}

synchronized void waitForAppUndeployment() {

    while (!appUndeployed) {

        try {

            wait();

        } catch (InterruptedException e) {
        }

    }

}

public Main() {

}

public Main(String filename) {

    setProperties(filename);

}

private final static String SyntaxHelp = "syntax:\\n\\tdeploy \\n\\tundeploy ";

private final static String PropertiesFilename = "wardeployment.properties";

private Properties deploymentProperties;

private void setProperties(String filename) {

    FileInputStream fis = null;

    try {

        fis = new FileInputStream(filename);

        deploymentProperties = new Properties();

        deploymentProperties.load(fis);

        fis.close();

    } catch (FileNotFoundException ex) {

        ex.printStackTrace();

    } catch (IOException ex) {

        ex.printStackTrace();

    }

}

private static void printHelpAndExit() {

    System.out.println(SyntaxHelp);

    System.exit(1);

}

public static void main(String[] args) {

    if (args.length < 1) {

        printHelpAndExit();

    }

    Main worker = new Main(PropertiesFilename);

    if ("deploy".equals(args[0])) {

        System.out.println("Deploying app...");
        String warContext = new File(args[1]).getName();
        warContext = warContext.substring(0, warContext.length() - 4);

        worker.runApp(args[1], warContext);

        worker.releaseDeploymentManager();

    } else if ("undeploy".equals(args[0])) {

        System.out.println("Undeploying app...");
        String warContext = new File(args[1]).getName();
        warContext = warContext.substring(0, warContext.lastIndexOf("."));

        worker.undeployApp(warContext);

        worker.releaseDeploymentManager();

        }

    }

}

The modified wardeployment.propertiesfile is given hereunder:

jsr88.dm.id=deployer:Sun:AppServer::10.9.80.117:4848
jsr88.dm.user=admin
jsr88.dm.passwd=adminadmin
jsr88.df.classname=org.glassfish.deployapi.SunDeploymentFactory

You need to add javaee-api-7.0.jar and development-client.jar files in your classpath. You can find development-client.jar in your glassfish installation directory under "glassfish-4.0\glassfish\modules\" directory.

UPDATE: I tested the application from Netbeans 7.4 and it worked within the IDE however outside of the IDE it generated an error message which was not easy to fix as there was no clue where the problem is. The error message was

javax.enterprise.deploy.spi.exceptions.DeploymentManagerCreationException: Could not get DeploymentManager

The basic reason was that some required libraries were missing. After going through the whole list of glassfish libraries, I figuired out that the following libraries were required if we want to run the application stand-alone. Find the complete list hereunder:

  1. admin-cli.jar
  2. admin-util.jar
  3. cglib.jar
  4. common-util.jar
  5. config-types.jar
  6. core.jar
  7. deployment-client.jar
  8. deployment-common.jar
  9. glassfish-api.jar
  10. hk2-api.jar
  11. hk2-config.jar
  12. hk2-locator.jar
  13. hk2-utils.jar
  14. internal-api.jar
  15. javax.enterprise.deploy-api.jar
  16. javax.inject.jar
  17. osgi-resource-locator.jar

Upvotes: 0

Javier Rengel
Javier Rengel

Reputation: 21

I think that the simplest way to automatically deploy applications in glassfish is using the autodeploy folder of glassfish (located in glassfish\domains\autodeploy ). Every war or jar that you copy to that folder will be automatically deployed in the server (if it works correctly).

So all you need to do is using a schedule control like Quartz and a couple of methods to copy files in the server (for example, to your working directory to the autodeploy folder).

Another option is to run shell scripts in your application with something like this

$ ./asadmin deploy --name \ --contextroot /absolute/path/to/.war

Upvotes: 0

Richard Sitze
Richard Sitze

Reputation: 8463

While glassfish can be started stand-alone, it can also be embedded into your own application (don't think Java EE here, but simple (or not so simple) Java app).

You could define a set of management APIs, startup and configure GlassFish, and manage that glassfish instance via those APIs. Exposing your APIs to applications running under glassfish should be feasible as well.

Upvotes: 1

Related Questions