Local service is for accessing third party java functions. It does not require server or network connection. Java Archive (JAR) file acts as "server", any public class with default constructor acts as "service", and all the public method can be called. Please mind that the build-in editor may hide methods that requires unsupported argument type. Direct access of the Marvin Services API does not have this restriction, any type can be used.
Local Service is the most easy way to embed third-party calculation to MarvinSketch application, cxcalc or Chemical Terms, however java coding is required to assemble the jar files. Also note that these services can not be accessed in non-java environment such as Marvin .NET or JChem for Excel.
Keep in mind that classes used via service call should be stateless, as each service call will create a new instance of the class by the default constructor before calling the function.
Local Service makes good use of the Alias
and Description
annotations. Any methods annotated can provide default names and description for services and arguments. Also, these aliases are available from cxcalc as well - so a default service and argument name can be guaranteed by the class author.
Calling Local Service from API
The following code snippet calls the Integer countAtoms(Molecule)
function of example.services.SampleService
class located in localserviceexample.jar.
// input molecule Molecule input = MolImporter.importMol("c1ccncc1"); // initialize descriptor LocalServiceDescriptor descriptor = new LocalServiceDescriptor(); descriptor.setURL("/path/to/localserviceexample.jar"); descriptor.setClassName("example.services.SampleService"); descriptor.setMethodName("countAtoms"); descriptor.addArgument(ServiceArgument.createArgument(new Molecule())); // asynchronous call descriptor.getServiceHandler().callService(descriptor, new AsyncCallback<Integer>() { @Override public void onSuccess(Integer result) { System.out.println("Asynchronous call returned " + result); } @Override public void onFailure(ServiceException caught) { System.err.println("Asynchronous call failed."); } }, input); // synchronized call Object result = null; try { result = descriptor.getServiceHandler().callService(descriptor, input); } catch (ServiceException e) { System.err.println("Service call failed."); } System.out.println("Synchronized call returned " + result);
Use annotations to define default names and description
Local Service can look up default service and argument names, as well as description information from annotations. These values used in MarvinSketch when adding the Local Service to the services list by automatically completing the form. The values can be edited manually, but the defaults are always available from Chemical Terms or cxcalc - as well as the optionally overwritten ones.
You can find a sample class can be used as a Local Service below. To download the sample service jar file with source, click here.
* * Copyright (c) 1998-2014 ChemAxon Ltd. All Rights Reserved. * * This software is the confidential and proprietary information of * ChemAxon. You shall not disclose such Confidential Information * and shall use it only in accordance with the terms of the agreements * you entered into with ChemAxon. * */ package example.services; import chemaxon.formats.MolFormatException; import chemaxon.formats.MolImporter; import chemaxon.marvin.services.localservice.Alias; import chemaxon.marvin.services.localservice.Description; import chemaxon.struc.Molecule; /** * This is a sample class to demonstrate how to write * classes for Marvin Services Local Service implementation. * @author Istvan Rabel */ public class SampleService { /** * Returns the number of atoms in the specified molecule * @param molecule the molecule being checked * @return the number of atoms in the molecule */ /* * (non-javadoc) * This method can be called as a LocalService from * Marvin Sketch, cxcalc and Chemical Terms. * Annotations are used to provide default names * for Service and arguments, as well as a description. */ @Alias(name="AtomCount", params={"Structure"}) @Description("Returns the number of atoms in the structure") public Integer countAtoms(Molecule molecule) { return molecule.getAtomCount(); } /** * Returns a formatted (HTML) message with the number of * atoms in the molecule imported from argument. * @param moleculeString a string representation of a molecule * @return a formatted (HTML) message with the number of atoms */ /* * (non-javadoc) * This method can be called as a LocalService from * Marvin Sketch, cxcalc and Chemical Terms. * Annotations are used to provide default names * for Service and arguments, as well as a description. */ @Alias(name="AtomCountText", params={"Molecule"}) @Description("Returns a formatted text message containing the number of atoms in the structure.") public String countAtomsHTML(String moleculeString) { // import the molecule Molecule molecule = null; try { molecule = MolImporter.importMol(moleculeString); } catch (MolFormatException e) { // invalid molecule string molecule = new Molecule(); } // get the atom count int value = countAtoms(molecule); // build and return the result string StringBuilder builder = new StringBuilder("<html><body>"); if(value > 1) { builder.append("The structure has <font color='blue'><b>"); builder.append(value); builder.append("</b></font> atoms."); } else { builder.append("The structure has <font color='red'><i>" + (value == 0 ? "no atoms" : "only one atom") + "</i></font>."); } builder.append("</body></html>"); return builder.toString(); } }