Eclipse RCP Standalone Client with Glassfish v3

This code fragment shows how an Eclipse RCP application can connect to Glassfish v3 as a stand-alone client (including full security). It consists of the following parts:

  • Eclipse plugin containing project-specific server classes, such remote interfaces for session beans and entity beans. It also contains all the necessary GFv3 Jars for the client app to run on a remote JVM. We call this : com.ansis.timetracker.client.lib.gf.
  • Eclipse client plugin(s). These plugins contain all the client-specific code and UI functionality. Each such plugin (here we provide one sample plugin) all depend on com.ansis.timetracker.client.lib.gf. It's name in our example is com.ansis.timetracker.client.

 

 Fragment 1: MANIFEST.MF of com.ansis.timetracker.client.lib.gf

 

The Bundle-ClassPath section contains two project specific Jars (aef-util.jar, timetracker.jar), which contain all necessary server classes (remote interfaces, etc.). All other Jars are identical to the Classpath section in the gf-client-module.jar found in the Glassfish/modules directory.

 

===========================================

Manifest-Version: 1.0

Bundle-ManifestVersion: 2

Bundle-Name: iREMS Server Plug-in

Bundle-SymbolicName: com.ansis.timetracker.client.lib.gf

Bundle-Version: 2.0.0.b1

Bundle-Vendor: ANSIS

Bundle-Localization: plugin

Bundle-ClassPath: lib/aef-util.jar,

 lib/timetracker.jar,

 srv_3_0_1/hk2-core.jar,

 srv_3_0_1/hk2.jar,

 srv_3_0_1/config.jar,

 srv_3_0_1/auto-depends.jar,

 srv_3_0_1/tiger-types-osgi.jar,

 srv_3_0_1/bean-validator.jar,

 srv_3_0_1/common-util.jar,

 srv_3_0_1/glassfish-api.jar,

 srv_3_0_1/config-types.jar,

 srv_3_0_1/grizzly-utils.jar,

 srv_3_0_1/management-api.jar,

 srv_3_0_1/javax.servlet.jar,

 srv_3_0_1/security.jar,

 srv_3_0_1/config-api.jar,

 srv_3_0_1/grizzly-config.jar,

 srv_3_0_1/grizzly-http.jar,

 srv_3_0_1/grizzly-framework.jar,

 srv_3_0_1/grizzly-rcm.jar,

 srv_3_0_1/grizzly-portunif.jar,

 srv_3_0_1/osgi-adapter.jar,

 srv_3_0_1/dol.jar,

 srv_3_0_1/endorsed/javax.annotation.jar,

 srv_3_0_1/javax.transaction.jar,

 srv_3_0_1/javax.enterprise.deploy.jar,

 srv_3_0_1/javax.persistence.jar,

 srv_3_0_1/javax.resource.jar,

 srv_3_0_1/javax.ejb.jar,

 srv_3_0_1/deployment-common.jar,

 srv_3_0_1/internal-api.jar,

 srv_3_0_1/asm-all-repackaged.jar,

 srv_3_0_1/annotation-framework.jar,

 srv_3_0_1/javax.security.auth.message.jar,

 srv_3_0_1/javax.security.jacc.jar,

 srv_3_0_1/ejb-internal-api.jar,

 srv_3_0_1/connectors-internal-api.jar,

 srv_3_0_1/transaction-internal-api.jar,

 srv_3_0_1/ldapbp-repackaged.jar,

 srv_3_0_1/gmbal.jar,

 srv_3_0_1/ejb-container.jar,

 srv_3_0_1/kernel.jar,

 srv_3_0_1/pkg-client.jar,

 srv_3_0_1/flashlight-framework.jar,

 srv_3_0_1/flashlight-agent.jar,

 srv_3_0_1/monitoring-core.jar,

 srv_3_0_1/stats77.jar,

 srv_3_0_1/deployment-javaee-core.jar,

 srv_3_0_1/container-common.jar,

 srv_3_0_1/glassfish-naming.jar,

 srv_3_0_1/admin-util.jar,

 srv_3_0_1/mail.jar,

 srv_3_0_1/activation.jar,

 srv_3_0_1/grizzly-comet.jar,

 srv_3_0_1/persistence-common.jar,

 srv_3_0_1/orb-connector.jar,

 srv_3_0_1/glassfish-corba-orbgeneric.jar,

 srv_3_0_1/glassfish-corba-omgapi.jar,

 srv_3_0_1/appclient.security.jar,

 srv_3_0_1/ejb.security.jar,

 srv_3_0_1/glassfish-corba-csiv2-idl.jar,

 srv_3_0_1/glassfish-corba-orb.jar,

 srv_3_0_1/glassfish-corba-newtimer.jar,

 srv_3_0_1/glassfish-corba-codegen.jar,

 srv_3_0_1/glassfish-corba-asm.jar,

 srv_3_0_1/orb-iiop.jar,

 srv_3_0_1/acc-config.jar,

 srv_3_0_1/webservices.security.jar,

 srv_3_0_1/web-glue.jar,

 srv_3_0_1/web-cli.jar,

 srv_3_0_1/cli-framework.jar,

 srv_3_0_1/amx-j2ee.jar,

 srv_3_0_1/amx-core.jar,

 srv_3_0_1/javax.management.j2ee.jar,

 srv_3_0_1/war-util.jar,

 srv_3_0_1/javax.servlet.jsp.jar,

 srv_3_0_1/web-naming.jar,

 srv_3_0_1/glassfish-ee-api.jar,

 srv_3_0_1/web-core.jar,

 srv_3_0_1/jsp-impl.jar,

 srv_3_0_1/el-impl.jar,

 srv_3_0_1/admin-core.jar,

 srv_3_0_1/web-gui-plugin-common.jar,

 srv_3_0_1/websecurity.jar,

 srv_3_0_1/webservices-osgi.jar,

 srv_3_0_1/jaxb-osgi.jar,

 srv_3_0_1/endorsed/jaxb-api-osgi.jar,

 srv_3_0_1/endorsed/webservices-api-osgi.jar,

 srv_3_0_1/woodstox-osgi.jar,

 srv_3_0_1/mimepull.jar,

 srv_3_0_1/jsr109-impl.jar,

 srv_3_0_1/grizzly-http-servlet.jar,

 srv_3_0_1/work-management.jar,

 srv_3_0_1/connectors-inbound-runtime.jar,

 srv_3_0_1/connectors-runtime.jar,

 srv_3_0_1/glassfish.jar,

 srv_3_0_1/jts.jar,

 srv_3_0_1/jta.jar,

 srv_3_0_1/jms-core.jar,

 srv_3_0_1/javax.jms.jar,

 srv_3_0_1/org.eclipse.persistence.core.jar,

 srv_3_0_1/org.eclipse.persistence.asm.jar,

 srv_3_0_1/org.eclipse.persistence.antlr.jar,

 srv_3_0_1/org.eclipse.persistence.jpa.jar,

 srv_3_0_1/org.eclipse.persistence.jpa.modelgen.jar,

 srv_3_0_1/org.eclipse.persistence.oracle.jar,

 srv_3_0_1/jpa-connector.jar,

 srv_3_0_1/cmp-internal-api.jar

Require-Bundle: org.eclipse.core.runtime;bundle-version="3.4.0"

Bundle-ActivationPolicy: lazy

Export-Package: com.ansis.aef.util,

 com.ansis.aef.util.audit.exception,

 com.ansis.aef.util.audit.feedback,

 com.ansis.aef.util.audit.logger,

 com.ansis.aef.util.audit.profiling,

 com.ansis.aef.util.io,

 com.ansis.aef.util.io.csv,

 com.ansis.aef.util.io.excel,

 com.ansis.aef.util.io.html,

 com.ansis.aef.util.io.stream,

 com.ansis.aef.util.manipulation,

 com.ansis.aef.util.manipulation.collection,

 com.ansis.aef.util.manipulation.number2words,

 com.ansis.aef.util.manipulation.security,

 com.ansis.aef.util.pattern.customsortable,

 com.ansis.aef.util.pattern.sortedtree,

 com.ansis.aef.util.pattern.treeitem,

 com.ansis.aef.util.ui.presentation,

 com.ansis.timetracker.client.lib.gf,

 com.ansis.timetracker.server,

 com.ansis.timetracker.server.exception,

 com.ansis.timetracker.server.model.helper,

 com.ansis.timetracker.server.model.person,

 com.ansis.timetracker.server.model.project,

 com.ansis.timetracker.server.session.remote,

 com.ansis.timetracker.server.util,

 com.sun.appserv.security,

 javax.ejb

 

As you can see, it lists all necessary GFv3 Jars, but only exports two necessary packages.

Fragment 2: Lookup Code in com.ansis.timetracker.client.lib.gf

 

The class called ConnectionDetails does all the work of looking up a requested session bean stub.

 

======== Listing ConnectionDetails.java ============

 

package com.ansis.timetracker.server.util;

 

import java.io.Serializable;

import java.util.HashMap;

import java.util.Map;

import java.util.Properties;

 

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.security.auth.login.AppConfigurationEntry;

import javax.security.auth.login.Configuration;

import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;

 

import com.ansis.aef.util.audit.logger.AEFLog;

import com.ansis.aef.util.audit.logger.AEFLogger;

import com.ansis.aef.util.manipulation.StringUtils;

import com.ansis.timetracker.server.exception.TTRuntimeException;

import com.ansis.timetracker.server.session.remote.ActivityTrackerBeanRemote;

import com.ansis.timetracker.server.session.remote.DashboardFacadeBeanRemote;

import com.sun.appserv.security.ProgrammaticLogin;

 

 

/**

 * Contains all the details necessary to connect to the iREMS server.

 * 

 * EJB FAQ: https://glassfish.dev.java.net/javaee5/ejb/EJB_FAQ.html

 * 

 * GF CORBA home page: https://glassfish-corba.dev.java.net/

 * 

 * RMI JVM settings: java.sun.com/j2se/1.4.2/docs/guide/rmi/sunrmiproperties.html

 * 

 * Performance tuning RMI/J2EE: www.javaperformancetuning.com/tips/j2ee_rmi.shtml

 * 

 * 

 * Connecting standalone client to GFv3:

 * https://glassfish.dev.java.net/javaee5/ejb/EJB_FAQ.html#StandaloneRemoteEJB

 * forums1.java.net/jive/message.jspa

 * forums.java.net/jive/message.jspa

 * 

 * @author akozma

 * Copyright ANSIS, 2010: please reference ANSIS when reusing. 

 */

@SuppressWarnings("nls")

public class ConnectionDetails implements Serializable {

 

// ==================== 1. Static Fields ========================

 

private static final long serialVersionUID = -4710045391762303501L;

 

private static AEFLog log = AEFLogger.getLogger(ConnectionDetails.class);

 

private static final String PORT_SEPARATOR = ":";

 

private static final String DEFAULT_HOST = "localhost";

 

private static final String PROD_PORT_ALIASES = "p, prod, production";

private static final String SANDBOX_PORT_ALIASES = "s, , sb, test, sandb, sandbox";

 

 

// ====================== 2. Instance Fields =============================

 

private String user;

private String password;

private String server;

 

private String customPort;

 

private InitialContext context;

 

/**

* Remote server bean object.

*/

private ActivityTrackerBeanRemote activityTrackerBean = null;

 

private DashboardFacadeBeanRemote dashboardFacade = null;

 

// ==================== 4. Constructors ====================

 

/**

* Server is localhost with default port.

*/

public ConnectionDetails(final String user, final String password) {

this(user, password, "localhost");

}

 

/**

* Creates the initial context and sets the Security Context. 

* Please note that if a host address without is port is supplied, then the appropriate port

* number is appended automatically.

* @param user

* @param server

* @param port TODO

* @param MD5 encoded password

*/

public ConnectionDetails(final String user, final String password, final String server) {

setUser(user);

setPassword(password);

setServer(server);

 

}

 

// ==================== 7. Getters & Setters ====================

 

public String getUser() {

return user;

}

 

public void setUser(final String user) {

this.user = user;

}

 

public String getPassword() {

return password;

}

 

public void setPassword(final String password) {

this.password = password;

}

 

 

public String getServer() {

return server;

}

 

public void setServer(final String server) {

this.server = server;

}

 

// ==================== 8. Business Methods ====================

 

@SuppressWarnings("unchecked")

public <T> T lookup(final Class<T> remoteInterface, final String jndiName) {

 

try {

return (T) getInitialContext().lookup(jndiName);

} catch (final NamingException e) {

throw new TTRuntimeException("Error looking up remote interface for: " + jndiName, e);

}

 

}

 

/**

* Creates an initial context to login to the server.

*/

public Context getInitialContext() {

 

if (context != null)

return context;

 

// --------------------- <Set JAAS Config, so we don't have to read from config file> -----------------------

 

Configuration.setConfiguration(new Configuration() {

 

@Override

public AppConfigurationEntry[] getAppConfigurationEntry(final String name) {

 

final Map<String,Boolean> options = new HashMap<String, Boolean>();

options.put("debug", new Boolean(false));

 

if ("default".equals(name))

return new AppConfigurationEntry[] {new AppConfigurationEntry("com.sun.enterprise.security.auth.login.ClientPasswordLoginModule", LoginModuleControlFlag.REQUIRED, options)};

if ("certificate".equals(name))

return new AppConfigurationEntry[] {new AppConfigurationEntry("com.sun.enterprise.security.auth.login.ClientCertificateLoginModule", LoginModuleControlFlag.REQUIRED, options)};

 

throw new TTRuntimeException("New Configuration was asked for: " + name + ", but it should have been default or certificate!");

}

 

@Override

public void refresh() {

// we don't need to refresh anything!

}

 

});

 

final ProgrammaticLogin pm = new ProgrammaticLogin();

final boolean success = pm.login(getUser(), getPassword()); 

if (!success)

log.warn("Setup of login unsuccessful!");

 

   try {

context = new InitialContext(createPropertiesExisting());

} catch (final NamingException e) {

throw new TTRuntimeException("Error while logging in", e);

}

 

return context;

}

 

/**

* That's the default initial naming factory that works with Dynamic RMI/IIOP stub generation.

* @return

*/

private Properties createPropertiesExisting() {

 

final Properties props = new Properties(); 

   props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");

   props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming"); 

   props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl"); 

   

   // Only needed if server is running on a different host than localhost:

   if (!StringUtils.isEmpty(getServer()))

    props.setProperty("org.omg.CORBA.ORBInitialHost", getServer()); 

   // Optional.  Defaults to 3700.  Only needed if target orb port is not 3700.

   if (!StringUtils.isEmpty(getPortNumber()))

    props.setProperty("org.omg.CORBA.ORBInitialPort", getPortNumber()); 

   

// props.setProperty("com.sun.appserv.iiop.orbconnections","5");

//

// //Increase ORB Response Timeout to 2 hours instead of 30 min:

// props.setProperty("com.sun.corba.ee.transport.ORBTCPTimeouts", "500:90000:20"); 

// props.setProperty("com.sun.corba.ee.transport.ORBWaitForResponseTimeout", "7200000"); 

   

   return props;

}

 

public ActivityTrackerBeanRemote getActivityTrackerBean() {

 

if (activityTrackerBean == null) {

activityTrackerBean = lookup(ActivityTrackerBeanRemote.class, ActivityTrackerBeanRemote.JNDIName);

}

 

 

return activityTrackerBean;

}

 

/**

* @return the bean object on the remote server.

*/

public DashboardFacadeBeanRemote getDashboardFacadeBean() {

 

if (dashboardFacade == null) {

dashboardFacade = lookup(DashboardFacadeBeanRemote.class, DashboardFacadeBeanRemote.JNDIName);

}

 

 

return dashboardFacade;

}

 

public void resetBeans() {

activityTrackerBean = null;

dashboardFacade = null;

}

 

// ==================== 12. Presentation ====================

 

private String getPortNumber() {

return "30037";

}

 

@Override

public String toString() {

return "";

}

Fragment 3: MANIFEST.MF of Client Code Plugin

 

Manifest-Version: 1.0

Bundle-ManifestVersion: 2

Bundle-Name: Time Tracker

Bundle-SymbolicName: com.ansis.timetracker.client; singleton:=true

Bundle-Version: 2.0.0

Bundle-Activator: com.ansis.timetracker.client.ClientActivator

Bundle-Vendor: ANSIS

Bundle-Localization: plugin

Require-Bundle: org.eclipse.ui;visibility:=reexport,

 org.eclipse.core.runtime;visibility:=reexport,

 org.eclipse.ui.forms;visibility:=reexport,

 org.eclipse.jface.text,

 org.eclipse.core.resources,

 org.eclipse.ui.editors,

 org.eclipse.ui.ide,

 com.ansis.timetracker.client.lib.gf;visibility:=reexport

Eclipse-LazyStart: true

Bundle-ClassPath: .,

 lib/nebula_cdatetime_0.9.0.jar

Export-Package: com.ansis.timetracker.client,

 com.ansis.timetracker.client.core,

 com.ansis.timetracker.client.dialogs,

 com.ansis.timetracker.client.views,

 com.ansis.timetracker.client.views.components,

 com.ansis.timetracker.client.wizards,

 org.eclipse.swt.nebula.widgets.cdatet

Fragment 4: Code in Client Plugin using Session Bean Stubs

 

This code simply uses the SessionBean Remote Interface and calls its methods:

 

DashboardFacadeBeanRemote dashboard = getConnection().getDashboardFacadeBean();

 

dashboard.run