Skip to main content
Jump to: navigation, search

EclipseLink/Development/DBWS/OSGi/AdvCustIIAutoGen

< EclipseLink‎ | Development‎ | DBWS‎ | OSGi


Advanced Customization - Part II: Auto-generation of EclipseLink metadata

The files under META-INF and wsdl (eclipselink-dbws.xml, eclipselink-dbws-or.xml, etc.) can be generated at runtime when the Activator is first initialized. Starting with EclipseLink 2.1.2, portions of the initialization of org.eclipse.persistence.internal.dbws.ProviderHelper can be sub-classed:

protected InputStream initXRServiceStream(ClassLoader parentClassLoader, ServletContext sc) {
...
 
protected InputStream initXRSchemaStream(ClassLoader parentClassLoader, ServletContext sc) {
...
 
protected InputStream initWSDLInputStream(ClassLoader parentClassLoader, ServletContext sc) {
....

From the EclipseLink installation, add eclipselink-dbwsutils.jar and javax.wsdl_1.6.2.v200806030405.jar to the SimpleTable project, under a lib dir:
EclipseLinkExamplesOSGiDeveloping extraLibJars.png

Open the MANIFEST.MF file in the 'Plug-in Manifest Editor' and select the 'Runtime' tab and add the above jars to the plug-in's classpath: EclipseLinkExamplesOSGiDeveloping runtimeClasspath.png

The wsdl directory can be removed, along with all the DBWS files under META-INF (the project no longer needs these directories to be 'src' directories).

DBWSBuilder is normally invoked as a command-line tool along with a file containing 'operations' that are converted to DBWS runtime artifacts (eclipselink-dbws.xml, eclipselink-dbws-or.xml, etc.) It is also possible to program an instance of DBWSBuilder:

.... additional constants
//database properties
public static final String DATABASE_URL =
    "jdbc:derby:test;create=true";
public static final String DATABASE_DRIVER = 
    "org.apache.derby.jdbc.EmbeddedDriver";
public static final String DATABASE_PLATFORM = 
    "org.eclipse.persistence.platform.database.DerbyPlatform";
 
... additional imports in simpletable.Activator
//EclipseLink imports
import org.eclipse.persistence.internal.databaseaccess.Platform;
import org.eclipse.persistence.internal.dbws.ProviderHelper;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.xr.ProjectHelper;
import org.eclipse.persistence.internal.xr.XRDynamicClassLoader;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLLogin;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.DatabaseSession;
import org.eclipse.persistence.sessions.DatasourceLogin;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.factories.XMLProjectReader;
import org.eclipse.persistence.tools.dbws.DBWSBuilder;
import org.eclipse.persistence.tools.dbws.JavasePackager;
import org.eclipse.persistence.tools.dbws.TableOperationModel;
import static org.eclipse.persistence.logging.AbstractSessionLog.translateStringToLoggingLevel;
import static org.eclipse.persistence.tools.dbws.DBWSBuilder.NO_SESSIONS_FILENAME;
import static org.eclipse.persistence.tools.dbws.DBWSBuilder.SESSIONS_FILENAME_KEY;
import static org.eclipse.persistence.tools.dbws.DBWSPackager.ArchiveUse.noArchive;
import static org.eclipse.persistence.tools.dbws.XRPackager.__nullStream;
 
... additional member variables in simpletable.Activator
 
private static DBWSBuilder builder = new DBWSBuilder();
private static ByteArrayOutputStream DBWS_SERVICE_STREAM = new ByteArrayOutputStream();
private static ByteArrayOutputStream DBWS_SCHEMA_STREAM = new ByteArrayOutputStream();
private static ByteArrayOutputStream DBWS_OR_STREAM = new ByteArrayOutputStream();
private static ByteArrayOutputStream DBWS_OX_STREAM = new ByteArrayOutputStream();
private static ByteArrayOutputStream DBWS_WSDL_STREAM = new ByteArrayOutputStream();
 
... additional setup required when bundle starts
public void start(BundleContext bundleContext) throws Exception {
    Activator.context = bundleContext;
 
    builder.quiet = true;
    //set properties
    builder.setProjectName("simpletable");
    builder.setLogLevel(SessionLog.FINE_LABEL);
    builder.setDriver(DATABASE_DRIVER);
    builder.setPlatformClassname(DATABASE_PLATFORM);
    builder.setUrl(DATABASE_URL);
    builder.getProperties().put(SESSIONS_FILENAME_KEY, NO_SESSIONS_FILENAME);
    TableOperationModel tModel = new TableOperationModel();
    tModel.setName("simpleTable");
    tModel.setTablePattern("SIMPLETABLE");
    builder.getOperations().add(tModel);
    JavasePackager packager = new JavasePackager() {
	@Override
	public void start() {
		// normally start() checks for the existence of a temp directory -
		// no need since all DBWSBuilder artifacts are in-memory
	}
    };
    packager.setArchiveUse(noArchive);
    builder.setPackager(packager);
    try {
        // can't go thru java.sql.DriverManager 'cause it uses Class.forName() - not OSGi-friendly
        Driver driver = new org.apache.derby.jdbc.EmbeddedDriver();
        Connection conn = driver.connect(DATABASE_URL, null);
        builder.setConnection(conn);
    }
    catch (Exception e) {
        // find out what happened
        e.printStack();
	throw e;
    }
    builder.build(DBWS_SCHEMA_STREAM, __nullStream, DBWS_SERVICE_STREAM, DBWS_OR_STREAM,
       DBWS_OX_STREAM, __nullStream, __nullStream, DBWS_WSDL_STREAM, __nullStream, __nullStream,
       __nullStream, __nullStream, null);
    super.init(this.getClass().getClassLoader(), null, false);
 
    // regular setup of Endpoint
    endpoint = Endpoint.create(this);
    endpoint.publish(ENDPOINT_ADDRESS);   
    ....

The call to super.init(XRDynamicClassLoader, null, false) makes callbacks to the three init routines mentioned above where we return the information computed in builder.build(DBWS_SCHEMA_STREAM,...):

protected InputStream initXRServiceStream(ClassLoader parentClassLoader, ServletContext sc) {
    return new ByteArrayInputStream(DBWS_SERVICE_STREAM.toByteArray());
}
 
protected InputStream initXRSchemaStream(ClassLoader parentClassLoader, ServletContext sc) {
    return new ByteArrayInputStream(DBWS_SCHEMA_STREAM.toByteArray());
}
 
protected InputStream initWSDLInputStream(ClassLoader parentClassLoader, ServletContext sc) {
    return new ByteArrayInputStream(DBWS_WSDL_STREAM.toByteArray());
}
The final step is to build the EclipseLink sessions - Override buildSessions() (looks complicated but its just 'plumbing'):
...
import static org.eclipse.persistence.logging.AbstractSessionLog.translateStringToLoggingLevel;
...
@Override
public void buildSessions() {
    XRDynamicClassLoader xrdecl = new XRDynamicClassLoader(parentClassLoader);
    Project oxProject = XMLProjectReader.read(new StringReader(DBWS_OX_STREAM.toString()),
        xrdecl);
    ((XMLLogin)oxProject.getDatasourceLogin()).setEqualNamespaceResolvers(false);
    Project orProject = XMLProjectReader.read(new StringReader(DBWS_OR_STREAM.toString()),
        xrdecl);
    DatasourceLogin login = orProject.getLogin();
    ((DatabaseLogin)login).setConnectionString(builder.getUrl());
    ((DatabaseLogin)login).setDriverClassName(builder.getDriver());
    Platform platform = builder.getDatabasePlatform();
    ConversionManager cm = platform.getConversionManager();
    cm.setLoader(xrdecl);
    login.setDatasourcePlatform(platform);
    ((DatabaseLogin)login).bindAllParameters();
    orProject.setDatasourceLogin(login);
    ProjectHelper.fixOROXAccessors(orProject, oxProject);
    DatabaseSession databaseSession = orProject.createDatabaseSession();
    int logLevel = translateStringToLoggingLevel(builder.getLogLevel());
    if (SessionLog.OFF == logLevel) {
        databaseSession.dontLogMessages();
    }
    else {
        databaseSession.setLogLevel(logLevel); 
    }
    xrService.setORSession(databaseSession);
    xrService.setXMLContext(new XMLContext(oxProject));
    xrService.setOXSession(xrService.getXMLContext().getSession(0));
}

Back to the top