-
1. Re: Integration with OpenEJB
alrubinger Jan 21, 2010 4:11 PM (in response to alrubinger)Excuse my ugly prototyping code, but here's an example of Jetty integration using technique 1):
/* * JBoss, Home of Professional Open Source. * Copyright 2010, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.iface.jetty.impl.deployment; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.logging.Logger; import org.jboss.iface.jetty.spi.deployment.JettyShrinkWrapDeployer; import org.jboss.iface.jetty.spi.service.JettyService; import org.jboss.iface.spi.deployment.DeploymentException; import org.jboss.shrinkwrap.api.exporter.ZipExporter; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.mortbay.jetty.Server; import org.mortbay.jetty.servlet.Context; import org.mortbay.jetty.webapp.WebAppContext; /** * Deployment connector such that {@link JettyService} containers can * support ShrinkWrap {@link WebArchive} types. * * TODO: Undeployment * * TODO: PROTOTYPING IN PROGRESS * * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a> */ public class JettyShrinkWrapDeployerImpl implements JettyShrinkWrapDeployer { //-------------------------------------------------------------------------------------|| // Class Members ----------------------------------------------------------------------|| //-------------------------------------------------------------------------------------|| /** * Logger */ private static final Logger log = Logger.getLogger(JettyShrinkWrapDeployerImpl.class.getName()); /** * System property denoting the name of the temp directory */ private static final String SYSPROP_KEY_TMP_DIR = "java.io.tmpdir"; /** * Temporary directory into which we'll extract the {@link WebArchive}s */ private static final File TMP_DIR; static { TMP_DIR = new File(AccessController.doPrivileged(new PrivilegedAction<String>() { @Override public String run() { return System.getProperty(SYSPROP_KEY_TMP_DIR); } })); // If the temp location doesn't exist or isn't a directory if (!TMP_DIR.exists() || !TMP_DIR.isDirectory()) { throw new IllegalStateException("Could not obtain temp directory \"" + TMP_DIR.getAbsolutePath() + "\""); } } //-------------------------------------------------------------------------------------|| // Instance Members -------------------------------------------------------------------|| //-------------------------------------------------------------------------------------|| //-------------------------------------------------------------------------------------|| // Constructor ------------------------------------------------------------------------|| //-------------------------------------------------------------------------------------|| //-------------------------------------------------------------------------------------|| // Required Implementations -----------------------------------------------------------|| //-------------------------------------------------------------------------------------|| /** * {@inheritDoc} * @see org.jboss.iface.spi.deployment.Deployer#deploy(java.lang.Object, D[]) */ @Override public void deploy(final JettyService container, final WebArchive... deployables) throws DeploymentException, IllegalArgumentException { // Precondition check assertDeployables(deployables); // Get the server final Server server = container.getServer(); for (final WebArchive deployable : deployables) { // Flush to file final String name = deployable.getName(); final File exported = new File(TMP_DIR, deployable.getName()); deployable.as(ZipExporter.class).exportZip(exported); // Mark to delete when we come down exported.deleteOnExit(); // Add the context final URL url; try { url = exported.toURI().toURL(); } catch (final MalformedURLException e) { throw new RuntimeException("Could not obtain URL of File " + exported.getAbsolutePath(), e); } log.info("Webapp location: " + url); final Context context = new WebAppContext(url.toExternalForm(), "/" + name); server.addHandler(context); log.info("Deployed under context: " + name); } // Restart if necessary if (server.isRunning()) { try { container.stop(); } catch (final Exception e) { log.warning("Problem in stopping the server cleanly: " + e); } try { container.start(); } catch (final Exception e) { throw new RuntimeException(e); } } } /** * {@inheritDoc} * @see org.jboss.iface.spi.deployment.Deployer#undeploy(java.lang.Object, D[]) */ @Override public void undeploy(JettyService container, WebArchive... deployables) throws DeploymentException, IllegalArgumentException { // Precondition check assertDeployables(deployables); //TODO } //-------------------------------------------------------------------------------------|| // Internal Helper Methods ------------------------------------------------------------|| //-------------------------------------------------------------------------------------|| /** * Ensures deployables are specified */ private static void assertDeployables(final WebArchive... deployables) throws IllegalArgumentException { if (deployables == null) { throw new IllegalArgumentException("deployables must be specified"); } } }
-
2. Re: Integration with OpenEJB
dblevins Jan 21, 2010 7:50 PM (in response to alrubinger)The file approach seems easiest. Here's a test case that shows it:
We also have this other functionality and I don't know if this helps or not. But you can basically build the app via the jaxb tree for the EJbJar and pass that to us:
There's a third version which basically takes the EjbJar and wraps it as a EjbModule and then you can specify the file path and classloader you'd like to use. There's a AppModule version as well that allows you to put EjbModules and other types in it and deploy that as an ear.
Not sure if any of that helps. Maybe some sort of translation layer is possible? At a minimum seems the java.io.File approach would work fine.
-David
-
3. Re: Integration with OpenEJB
alrubinger Jan 21, 2010 7:56 PM (in response to dblevins)Pointers to similar testcases are exactly the type of thing I was looking for.
When I get some cycles next week I'll pull down source and see what I can hack up together.
S,
ALR
-
4. Re: Integration with OpenEJB
alrubinger Jan 23, 2010 9:52 PM (in response to dblevins)David:
Attached is a lil patch that gets the job done. Its test looks like:
// Create archive to hold our test EJB final String name = "echo.jar"; final JavaArchive archive = Archives.create(name, JavaArchive.class).addClasses(EchoBean.class, EchoLocalBusiness.class); logger.info("Created archive: " + archive.toString(true)); // These two objects pretty much encompass all the EJB Container final ConfigurationFactory config = new ConfigurationFactory(); final Assembler assembler = new Assembler(); assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class)); assembler.createSecurityService(config.configureService(SecurityServiceInfo.class)); // Deploy as an archive final AppInfo appInfo = config.configureApplication(archive); assembler.createApplication(appInfo); // Get a JNDI Context final Properties properties = new Properties(); properties.put(Context.INITIAL_CONTEXT_FACTORY, LocalInitialContextFactory.class.getName()); final Context ctx = new InitialContext(properties); // Lookup final EchoLocalBusiness bean = (EchoLocalBusiness) ctx.lookup(EchoBean.class.getSimpleName() + "Local"); // Invoke and test final String request = "Word up"; final String response = bean.echo(request); logger.info("Sent: \"" + request + "\"; got: \"" + response + "\""); TestCase.assertEquals("Response from EJB invocation not expected", request, response); TestCase.assertTrue("Response from local EJB invocation is equal by value but not by reference", request == response); // Undeploy the archive assembler.destroyApplication(appInfo.jarPath);
Gives output:
INFO - Created archive: echo.jar: /org/apache/openejb/assembler/classic/ejb/EchoBean.class /org/apache/openejb/assembler/classic/ejb/EchoLocalBusiness.class INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager) INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service) INFO - Configuring enterprise application: /tmp/1aa8ca17-f7ee-4f90-a306-3105580cd19e/echo.jar INFO - Configuring Service(id=Default Stateless Container, type=Container, provider-id=Default Stateless Container) INFO - Auto-creating a container for bean EchoBean: Container(type=STATELESS, id=Default Stateless Container) INFO - Enterprise application "/tmp/1aa8ca17-f7ee-4f90-a306-3105580cd19e/echo.jar" loaded. INFO - Assembling app: /tmp/1aa8ca17-f7ee-4f90-a306-3105580cd19e/echo.jar INFO - Jndi(name=EchoBeanLocal) --> Ejb(deployment-id=EchoBean) INFO - Created Ejb(deployment-id=EchoBean, ejb-name=EchoBean, container=Default Stateless Container) INFO - Deployed Application(path=/tmp/1aa8ca17-f7ee-4f90-a306-3105580cd19e/echo.jar) INFO - Sent: "Word up"; got: "Word up" INFO - Undeploying app: /tmp/1aa8ca17-f7ee-4f90-a306-3105580cd19e/echo.jar
The underlying mechanism is using File serialization for the time being. If we dig a little deeper and provide:
public AppModule load(String name, InputStream in) throws OpenEJBException;
...within DeploymentLoader we can avoid the disk I/O.
S,
ALR
-
5. Re: Integration with OpenEJB
dblevins Jan 25, 2010 11:11 PM (in response to alrubinger)This is great. We should give this thing it's own module, maybe under container/, and move the ConfigurationFactory changes into a new subclass called ShrinkWrapConfigurationFactory. Then we can really go nuts with changes.
Can you reattach your patch here? (need the "Grant license to ASF for inclusion in ASF works" option checked before i can check it in)
https://issues.apache.org/jira/browse/OPENEJB-1228
-David
-
6. Re: Integration with OpenEJB
alrubinger Jan 26, 2010 10:55 AM (in response to dblevins)Nice; attached.
Had you wanted us to do the moving, etc?
S,
ALR
-
7. Re: Integration with OpenEJB
dblevins Jan 26, 2010 12:33 PM (in response to alrubinger)If you want to do the subclass part, I can do the rest. -
8. Re: Integration with OpenEJB
alrubinger Jan 26, 2010 12:34 PM (in response to dblevins)Deal; I'll ping back here when done. -
9. Re: Integration with OpenEJB
alrubinger Jan 26, 2010 3:06 PM (in response to alrubinger)Done and attached a new patch to the issue.
S,
ALR