Skip to content
This repository has been archived by the owner. It is now read-only.

Latest commit

 

History

History
175 lines (116 loc) · 9.5 KB

README.md

File metadata and controls

175 lines (116 loc) · 9.5 KB

Keraiai

Welcome to Keraiai - a Java communication library for SFDC.

Build Status

Keraiai vs Lasius?

Currently, Lasius contains WSDLs for the Enterprise, Partner, Metadata and Tooling APIs...as well as similar communications functionality as found here. However, we decided to simplifiy the libraries:

  • Keraiai will provide all communications related functionality.
  • Lasius will provide other general utility functionality.

What Does Keraiai Mean?

Like all Solenopsis themes, we wanted to choose a Latin or Greek word related to ants. Since this is project is for SFDC communication, we considered an ant's antenna. The word keraiai is actually Greek and refers to an insect's horns.

Design Decisions

Interfaces Located Within Parent Packages

When an interface can be shared across sub-packages, we chose to define those interfaces in parent packages.

Enums

Implement Interfaces

If you browse the source code, you will note we make heavy use of enums which implement interfaces. Doing so allows us to more naturally decouple and allows us to mock implementations in our unit tests.

Declarative Model

You may note our enums are more than simple named markers - they contain code as well as what we consider a "declarative" model. As an example, refer to SessionUrlFactoryEnum. We have two varying pieces:

  • The sub-URL for a session.
  • The factory that computes the "name" of the web service. For some SFDC web services, one uses the API version as the name of the web service. For custom web services it is the name of the Apex class.

To illustrate:

  • Apex: ${SALESFORCE URL}/services/Soap/s/39.0
  • Custom: ${SALESFORCE URL}/services/Soap/class/Foo
  • Enterprise: ${SALESFORCE URL}/services/Soap/c/39.0
  • Metadata: ${SALESFORCE URL}/services/Soap/m/39.0
  • Partner: ${SALESFORCE URL}/services/Soap/u/39.0
  • Tooling: ${SALESFORCE URL}/services/Soap/T/39.0

Above you can see the sub-URL (services/Soap/[varying portion]) followed by the "name" of the webservice.

Using enums in this fashion allows us to declare how to do things vs if/else-if constructs. This keeps the code simple and clean.

How To

Creating Web Service Ports

Web service ports can be created using WebServiceTypeEnum's various createProxyPort() methods. The returned ports will manage auto login, and re-login should your session become invalid. A LoginMgr implementation is required and can be found in the following:

Please note: when omitted, the default LoginMgr is the Enterprise Login Manager in creating proxy ports.

Additionally, an implementation of Credentials is needed whe creating a proxy port. The following implementations are provided for your convenience:

Examples

Assume your credentials exist in ${HOME}/sfdc.properties and contain the following fictitious values:

username   = myuser@mycompany.com
password   = MyPassword
token      = abcdefghijklmnopqrstuvwxy
url        = https://test.salesforce.com
apiVersion = 34.0

Also assume your WSDLs are found in your home directory:

final FileInputStream fis = new FileInputStream("/home/myuser/sfdc.properties");

final Properties properties = new Properties();
properties.load(fis);

fis.close();

final Credentials credentials = new PropertiesCredentials(properties);
Apex Web Service
final ApexPortType apexPort = WebServiceTypeEnum.APEX_SERVICE_TYPE.createProxyPort(credentials, ApexService.class, MyClass.class.getClassLoader().getResource("/home/myuser/apex.wsdl");
Custom Web Service
final FooPortType fooPort = WebServiceTypeEnum.CUSTOM_SERVICE_TYPE.createProxyPort(credentials, FooService.class, MyClass.class.getClassLoader().getResource("/home/myuser/foo.wsdl");
Enterprise Web Service
final Soap enterprisePort = WebServiceTypeEnum.ENTERPRISE_SERVICE_TYPE.createProxyPort(credentials, SforceService.class, MyClass.class.getClassLoader().getResource("/home/myuser/enterprise.wsdl");
Metadata API Web Service
final MetadataPortType metadataPort = WebServiceTypeEnum.METADATA_SERVICE_TYPE.createProxyPort(credentials, MetadataService.class, MyClass.class.getClassLoader().getResource("/home/myuser/metadata.wsdl");
Partner Web Service
final Soap partnerPort = WebServiceTypeEnum.PARTNER_SERVICE_TYPE.createProxyPort(credentials, SforceService.class, MyClass.class.getClassLoader().getResource("/home/myuser/partner.wsdl");
Tooling API Web Service
final SforceServicePortType toolingPort = WebServiceTypeEnum.TOOLING_SERVICE_TYPE.createProxyPort(credentials, SforceServiceService.class, MyClass.class.getClassLoader().getResource("/home/myuser/tooling.wsdl");

The above can now be used like normal objects - there is no need to worry about session ids, logins, invalid session ids, etc. All will be managed for you - and likely you can share the ports without needing to create ports for indivdual use cases. It may be desirable to create a static utility/context class containing your port instances that can be used across your application. Using the above as an example, suppose your application needs to use both the fooPort and enterprisePort:

public static final class SessionContext {
    public static final FooPortType FOO_PORT;
    public static final Soap ENTERPRISE_PORT;

    static {
        try(final FileInputStream fis = new FileInputStream("/home/myuser/sfdc.properties")) {

            final Properties properties = new Properties();
            properties.load(fis);

            final Credentials credentials = new PropertiesCredentials(properties);
            final SecurityMgr securityMgr = new EnterpriseSecurityMgr(credentials);

            FOO_PORT = WebServiceTypeEnum.CUSTOM_SERVICE_TYPE.createProxyPort(credentials, FooService.class, MyClass.class.getClassLoader().getResource("/home/myuser/foo.wsdl");
            ENTERPRISE_PORT = WebServiceTypeEnum.ENTERPRISE_SERVICE_TYPE.createProxyPortcredentials, SforceService.class, MyClass.class.getClassLoader().getResource("/home/myuser/enterprise.wsdl");
        }
    } catch (final IOException ioException) {
        // Do something...
    }
    
    private SessionContext() {
    }
}

Now your application can simply use SessionContext with no regard to logins, etc.

Getting Your LoginContext

Above we illustrated how to create and use a proxy port. You can also get your current LoginContext by casting the proxy port to a LoginContext. This works, because the proxy port implements both the web service port and LoginContext interfaces!

Examples

final MetadataPortType metadataPort = WebServiceTypeEnum.METADATA_SERVICE_TYPE.createProxyPort(credentials, MetadataService.class, MyClass.class.getClassLoader().getResource("/home/myuser/metadata.wsdl");

final LoginContext loginContext = (LoginContext) metadataPort;

The advantage here is that your LoginContext implicitly follows your web service port.

Links

You may find the following links useful: