Diagram 1. Service Invocation From Client System Overview:

This chapter describes methods of calling services using:

1. Remote calling of JLupin Java Remote Object Invocation Protocol

2. Calls using WEB SERVICE-SOAP-XML FACADE PATTERN

3. Calls using WEB SERVICE-HTTP-JSON FACADE PATTERN

Description of item 1.

Service interface:

package com.jlupin.sampleapp.paramsfunction.service;

public interface DigestService {
    String getMD5Digest(String name, String surname) throws Throwable;
}

Implementation:

package com.jlupin.sampleapp.paramsfunction.service.impl;

import com.jlupin.interfaces.service.access.annotation.JLupinServiceAccessMode;
import com.jlupin.interfaces.service.access.enums.JLupinServiceAccessModeEnum;
import com.jlupin.sampleapp.paramsfunction.service.DigestService;
import org.springframework.stereotype.Service;
import java.security.MessageDigest;

@JLupinServiceAccessMode(mode = JLupinServiceAccessModeEnum.PUBLIC)
@Service("digestService")
public class DigestServiceImpl implements DigestService {

    public DigestServiceImpl() {
    }

    @Override
    public String getMD5Digest(String name, String surname) throws Throwable {
            String stringToDigest = name+surname;
            MessageDigest  messageDigest = MessageDigest.getInstance("MD5");
            byte [] buffer = stringToDigest.getBytes();
            messageDigest.update(buffer);
            byte [] digestBuffer  = messageDigest.digest();
            return byteToHex(digestBuffer);
    }

    private String byteToHex(byte in[]) {
        byte ch = 0x00;
        int i = 0;
        if (in == null || in.length <= 0) {
            return null;
        }
        StringBuilder out = new StringBuilder(in.length * 2);

        while (i < in.length) {
            ch = (byte) (in[i] & 0xF0);
            ch = (byte) (ch >>> 4);
            ch = (byte) (ch & 0x0F);
            out.append(pseudo[ (int) ch]);
            ch = (byte) (in[i] & 0x0F);
            out.append(pseudo[ (int) ch]);
            i++;
        }
        return out.toString();
    }

    private char pseudo[] = {'0', '1', '2', '3', '4', '5', '6', '7','8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
}

Test class:

public class InvokeTest {

    private JLupinLogger jLupinLogger;
    private JLupinProxyObjectProducer jLupinProxyObjectProducer;

    @Before
    public void before() {
        JLupinSimpleSystemOutLoggerImpl.initializeWithLogMode(LogMode.DEBUG);
        jLupinLogger     = JLupinSimpleSystemOutLoggerImpl.getInstance();

        JLupinSerializer jLupinSerializer = JLupinFSTSerializerImpl.getInstance();

        JLupinSocketDelegatorImpl jLupinDelegator = new JLupinSocketDelegatorImpl(jLupinLogger, jLupinSerializer);
        jLupinDelegator.setSocketAddressToConnectServer(new InetSocketAddress("localhost", 9090));
        jLupinDelegator.setReadTimeout(30000);
        jLupinDelegator.setConnectionTimeout(1000);

        jLupinProxyObjectProducer = new JLupinDefaultProxyObjectProducerImpl("firstSampleApplication","testClientApplication",jLupinDelegator, jLupinLogger);
    }

    @org.junit.Test
    public void test() throws Throwable {
        DigestService digestService = produceDigestService();
        String digest = digestService.getMD5Digest("name", "surname");
        jLupinLogger.info("digest:" + digest);
    }

    private DigestService produceDigestService() throws Throwable {
        JLupinInputParameter jLupinInputParameter = new JLupinInputParameter();
        jLupinInputParameter.setServiceName("digestService");
        return jLupinProxyObjectProducer.produceObject(DigestService.class, jLupinInputParameter);
    }
}

Description of calling:
The before method:
First, we prepare the logger and the serializer.

JLupinSimpleSystemOutLoggerImpl.initializeWithLogMode(LogMode.DEBUG);
JLupinLogger jLupinLogger         = JLupinSimpleSystemOutLoggerImpl.getInstance();
JLupinSerializer jLupinSerializer = JLupinFSTSerializerImpl.getInstance();

Then, we define the delegator.

JLupinSocketDelegatorImpl jLupinDelegator = new JLupinSocketDelegatorImpl(jLupinLogger, jLupinSerializer);
jLupinDelegator.setSocketAddressToConnectServer(new InetSocketAddress("localhost", 9090));
jLupinDelegator.setReadTimeout(30000);
jLupinDelegator.setConnectionTimeout(1000);

The configuration and the connection are carried out via the implementation of the JLupinDelegator interface. In this case the JLupinSocketDelegatorImpl implementation will be used which is combined into a single address and port.

The next step is to create and configure the creator of interfaces of remote services.

Good practice tip: The interfaces for the services should be placed in a separate module (for example, Maven) and compiled into a separate JAR file (e.g. common-interfaces.jar), so on the client side on the classpath put only the service interfaces instead of full services.

The interface that is responsible for creating the interfaces for remote services is JLupinProxyObjectProducer.

JLupin provides two of its implementations:

JLupinDefaultProxyObjectProducerImpl

allows creating an interface for the remote service. At the time of triggering the remote method, when an error occurs, JLupinCommandException will be thrown and it will have an error message prepared by exception handler that acts on the side of the server

JLupinProxyObjectSupportsExceptionProducerImpl

JLupinProxyObjectSupportsExceptionProducerImpl - allows creating an interface for the remote service. When calling the method the exception triggered is the remote exception triggered directly by the remote service - the messages created by the exception handler on the server side will be ignored.

In this example we will use the JLupinDefaultProxyObjectProducerImpl instance.

jLupinProxyObjectProducer = new JLupinDefaultProxyObjectProducerImpl("firstSampleApplication","testClientApplication",jLupinDelegator, jLupinLogger);

As the first parameter there is the name of the microservice to/from which the data exchange is to take place.
The second parameter is the name of the client application from which the services are called (e.g. for audit purposes on the server side). The third is a specific delegator (let us remind you that depending on the type of the delegator we can refer directly to a given server, an external load balancer or use JLupin`s software load balancers). The fourth is a logger.

The

produceDigestService()

method:
We create a transport object – DTO – JLupinInputPatameter. In the following parameters of the constructor we provide as follows: service name, session id, request id, ip, locale, user name. The last parameter can be an array of user autorization. In the next step a remote interface is produced. It can be used to perform remote class operations:

JLupinInputParameter jLupinInputParameter = new JLupinInputParameter("digestService","sessionId", "requestId",ip,new Locale("pl"), userName, new String[] {"user_privilege_1", "user_privilege_2"});

DigestService digestService = jLupinProxyObjectProducer.produceObject(DigestService.class, jLupinInputParameter);

The test method:

DigestService digestService = produceDigestService();
String digest = digestService.getMD5Digest("name", "surname");
jLupinLogger.info("digest:" + digest);

It simply calls the remote getMD5Digest method on the server using the JLupinSocketDelegatorImpl delegator. If you use the JLupinSocketDelegatorImpl delegator - as in the example above - the communication will look like in the following patterns. Direct calling of a particular server (left pattern), calling via an external load balancer (right pattern):

Along with the use of the JLupinDefaultBalanceProxyDelegatorImpl delegator - we can use a specific implementation of the software load balancer - see the chapter on Load Balancers. The configuration code to use the software load balancers is shown below (in our configuration we have two servers with different addresses: 198.162.8.3 and 198.162.9.3 and the below load balancer is configured on their addresses – of course it is only an example):

JLupinClientSocketConfiguration clientSocketConfServer_1 = new JLupinClientSocketConfiguration();

clientSocketConfServer_1.setSocketAddressToConnectServer(new InetSocketAddress("198.162.8.3", 8083));
clientSocketConfServer_1.setConnectionTimeout(1000);
clientSocketConfServer_1.setReadTimeout(30000);

JLupinClientSocketConfiguration clientSocketConfServer_2 = new JLupinClientSocketConfiguration();

clientSocketConfServer_2.setSocketAddressToConnectServer(new InetSocketAddress("198.162.9.3", 8083));
clientSocketConfServer_2.setConnectionTimeout(1000);
clientSocketConfServer_2.setReadTimeout(30000);

JLupinBalancer jLupinBalancer = new JLupinHealthCheckingSocketBalancerImpl(2, jLupinLogger,jLupinSerializer,"firstSampleApplication",1000, clientSocketConfServer_1,clientSocketConfServer_2);

In the below example in JLupinDefaultProxyObjectProducerImpl class we change only JLupinDelegator – flow will take place by software load balancer (JLupinHealthCheckingSocketBalancerImpl) provided with JLupin Next Server
Which means:

JLupinDelegator jLupinDelegator = new JLupinDefaultBalanceProxyDelegatorImpl(jLupinBalancer);
jLupinProxyObjectProducer = new JLupinDefaultProxyObjectProducerImpl("firstSampleApplication","testClientApplication",jLupinDelegator, jLupinLogger);

Then, traffic will balanced directly from the level of the application - as shown in the following pattern:

The difference between the JLupinSocketDelegatorImpl delegators (with the external load balancer) and JLupinDefaultBalanceProxyDelegatorImpl (with JLupinHealthCheckingSocketBalancerImpl) is shown in the pattern below:

Let’s take a look at JLupinProxyObjectSupportsExceptionProducerImpl.

As mentioned before it allows creating an interface for the remote service. When calling the method the exception triggered is the remote exception triggered directly by the remote service - the messages created by the exception handler on the server side will be ignored.

Let’s create maven project named sample-exception. It will have two modules and test class to be triggered.

Modules:
sample-exception-common – compiled to sample-exception-common.jar
sample-exception-impl – compiled to sample-exception-impl.jar

Let’s create two java files in sample-exception-common. Exception class (SampleException.java):

package com.jlupin.sampleapp.paramsfunction.service.exception;

public class SampleException extends Exception{
    public SampleException(String message) {
        super(message);
    }

    public SampleException(String message, Throwable cause) {
        super(message, cause);
    }
}

Service interface (SampleExceptionService.java):

package com.jlupin.sampleapp.paramsfunction.service;

import com.jlupin.sampleapp.paramsfunction.service.exception.SampleException;

public interface SampleExceptionService {
         void foo() throws SampleException;
}

Let’s create a java file in sample-exception-impl. Service class (SampleExceptionServiceImpl.java):

package com.jlupin.sampleapp.paramsfunction.service.impl;

import com.jlupin.sampleapp.paramsfunction.service.SampleExceptionService;
import com.jlupin.sampleapp.paramsfunction.service.exception.SampleException;

public class SampleExceptionServiceImpl implements SampleExceptionService {

    @Override
    public void foo() throws SampleException {
           throw new SampleException("sample exception");
    }
}

This class throws only SampleException.

Let’s configure the service by giving annotation of __@Service__ or by spring configuration file. Let’s take a look at the test class. In this example let’s use JLupinDefaultProxyObjectProducerImpl class again that, in case of an exception, triggers JLupinCommandException. Let’s check triggering effects:

Code of test class:

package com.jlupin.test.invoke;

import com.jlupin.impl.client.delegator.JLupinSocketDelegatorImpl;
import com.jlupin.impl.client.proxy.producer.JLupinDefaultProxyObjectProducerImpl;
import com.jlupin.impl.logger.impl.simple.stdout.JLupinSimpleSystemOutLoggerImpl;
import com.jlupin.impl.serialize.JLupinFSTSerializerImpl;
import com.jlupin.interfaces.client.proxy.producer.JLupinProxyObjectProducer;
import com.jlupin.interfaces.common.to.JLupinInputParameter;
import com.jlupin.interfaces.logger.JLupinLogger;
import com.jlupin.interfaces.logger.enums.LogMode;
import com.jlupin.interfaces.serialize.JLupinSerializer;
import com.jlupin.sampleapp.paramsfunction.service.SampleExceptionService;
import org.junit.Before;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Locale;

public class InvokeTest {

    private JLupinLogger jLupinLogger;
    private JLupinProxyObjectProducer jLupinProxyObjectProducer;

    @Before
    public void before() {
        JLupinSimpleSystemOutLoggerImpl.initializeWithLogMode(LogMode.DEBUG);
        jLupinLogger     = JLupinSimpleSystemOutLoggerImpl.getInstance();
        JLupinSerializer jLupinSerializer = JLupinFSTSerializerImpl.getInstance();
        JLupinSocketDelegatorImpl jLupinDelegator = new JLupinSocketDelegatorImpl(jLupinLogger, jLupinSerializer);
        jLupinDelegator.setSocketAddressToConnectServer(new InetSocketAddress("localhost", 9090));
        jLupinDelegator.setReadTimeout(30000);
        jLupinDelegator.setConnectionTimeout(1000);

        jLupinProxyObjectProducer = new JLupinDefaultProxyObjectProducerImpl("firstSampleApplication","testClientApplication",jLupinDelegator, jLupinLogger);

    }

    @org.junit.Test
    public void test() throws Throwable {
        try {
            SampleExceptionService sampleExceptionService = produceSampleExceptionService();
            sampleExceptionService.foo();
        } catch (Throwable throwable) {
                 throwable.printStackTrace();
        }
    }

    private SampleExceptionService produceSampleExceptionService() throws Throwable {
        JLupinInputParameter jLupinInputParameter = new JLupinInputParameter();
        jLupinInputParameter.setServiceName("
        return jLupinProxyObjectProducer.produceObject(SampleExceptionService.class, jLupinInputParameter);
    }
}

Triggering effect:
We present only a part of stack trace:

Caused by: com.jlupin.interfaces.client.command.exception.JLupinCommandException: unexpected error occurred while trying to call service sampleExceptionService and method foo, error details: sample exception

As shown, JLupinCommandException is an exception obtained on the side of the client, and error message is a message built by JLupinDefaultServiceExceptionHandlerImpl on the side of the server.

unexpected error occurred while trying to call service sampleExceptionService and method foo, error details: sample exception

Let’s now check what happens, if we change JLupinDefaultProxyObjectProducerImpl to JLupinProxyObjectSupportsExceptionProducerImpl

jLupinProxyObjectProducer = new JLupinProxyObjectSupportsExceptionProducerImpl("firstSampleApplication", "testClientApplication",jLupinDelegator, jLupinLogger);

Triggering effect (complete stack strace):

com.jlupin.sampleapp.paramsfunction.service.exception.SampleException: sample exception
    at com.jlupin.sampleapp.paramsfunction.service.impl.SampleExceptionServiceImpl.foo(SampleExceptionServiceImpl.java:11)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.jlupin.impl.util.JLupinUtil.invokeMethod(JLupinUtil.java:721)
    at com.jlupin.impl.processor.JLupinDefaultServiceProcessorImpl.invoke(JLupinDefaultServiceProcessorImpl.java:304)
    at com.jlupin.impl.entrypoint.defaults.strategy.invoke.impl.base.JLupinInvokeServiceStrategyBaseImpl.executeService(JLupinInvokeServiceStrategyBaseImpl.java:28)
    at com.jlupin.impl.entrypoint.defaults.strategy.invoke.impl.JLupinInvokeServiceStrategyInCurrentThreadImpl.invokeService(JLupinInvokeServiceStrategyInCurrentThreadImpl.java:36)
    at com.jlupin.impl.entrypoint.defaults.JLupinDefaultEntryPointImpl.doEntry(JLupinDefaultEntryPointImpl.java:35)
    at com.jlupin.impl.server.mainloop.strategy.base.JLupinBaseAbstractServiceStrategy$ThreadCallable.call(JLupinBaseAbstractServiceStrategy.java:102)
    at com.jlupin.impl.server.mainloop.strategy.base.JLupinBaseAbstractServiceStrategy$ThreadCallable.call(JLupinBaseAbstractServiceStrategy.java:84)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

As shown, SampleException declared and thrown on the side of the server is a triggering effect

Description of item 2.
Calls using WEB SERVICE-SOAP-XML FACADE PATTERN:

For more detailed information on how to create a message with Web Service - SOAP - XML read "Web Services as JLupin Web Services SOAP XML Facade Pattern"

Calling using Web Service - SOAP-XML – we call the service mentioned at the beginning of the section "digestService"
Input:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ent="http://entrypoint.impl.jlupin.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <ent:jLupinService>
         <jLupinInputParameter>
         <applicationName>firstSampleApplication</applicationName>
           <locale>pl</locale>
            <methodName>getMD5Digest</methodName>
              <privilegeList>
               <privilegeName>privilege</privilegeName>
            </privilegeList>
            <requestId>request1</requestId>
            <sequenceName>sampleParamArrayXmlInOutSequence</sequenceName>
             <serviceName>digestService</serviceName>
            <sessionId>session1</sessionId>
            <user>test_user</user>
             <busName>busName</busName>
             <paramArray><![CDATA[<string>name</string>;<string>surname</string>]]>
            </paramArray>
         </jLupinInputParameter>
     </ent:jLupinService>
   </soapenv:Body>
</soapenv:Envelope>

Output:

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
    <env:Header/>
    <env:Body>
        <jlns:jLupinServiceResponse xmlns:jlns="http://entrypoint.impl.jlupin.org/">
            <jLupinOutputParameter>
                <executedServiceError>false</executedServiceError>
                <result>
                    <![CDATA[<?xml version="1.0" encoding="UTF-8"?><java version="1.8.0_45" class="java.beans.XMLDecoder"><string>50382149719ab04e47a966ad959f4241</string>]]>
                </result>
            </jLupinOutputParameter>
        </jlns:jLupinServiceResponse>
    </env:Body>
</env:Envelope>

Description of item 3:
Calls using WEB SERVICE-HTTP-JSON FACADE PATTERN

For more detailed information on how to create a message using Web Service - HTTP JSON read "Web Services as JLupin HTTP-Rest Facade Pattern"

Calling using Web Service - HTTP JSON – called service mentioned at the beginning of the section "digestService":

Input:

{
  "jLupinInputParameter": {
    "applicationName": "firstSampleApplication",
    "locale": "pl",
    "methodName": "getMD5Digest",
    "privilegeList": [ "privilege_1", "privilege_2" ],
    "requestId": "request_1",
    "serviceName": "digestService",
    "sequenceName":"sampleParamArrayJsonInOutSequence",
    "paramArray":["java.lang.String:\"name\"","java.lang.String:\"surname\""],
    "sessionId": "session_1",
    "user": "test_user",
  }
}

Output:

{
  "jLupinOutputParameter": {
    "result": ""50382149719ab04e47a966ad959f4241"",
    "executedServiceError": false
  }
}