<?xml version="1.0" encoding="UTF-8"?>
<chapter id="sid-5931313">
   <title>Remote Procedure Calls (RPC)</title>
   <para>ErraiBus supports a high-level RPC layer to make typical client-server RPC communication easy on top of the bus. While it is possible to use ErraiBus without ever using this API, you may find it to be a more useful and concise approach for exposing services to the clients.</para>
   <para>Please note that this API has changed since version 1.0. RPC services provide a way of creating type-safe mechanisms to make client-to-server calls. Currently, this mechanism only support client-to-server calls, and not vice-versa.</para>
   <para>Creating a service is straight forward. It requires the definition of a remote interface, and a service class which implements it. See the following:</para>
   <informalexample>
      <programlisting language="java">
@Remote
public interface MyRemoteService {
  public boolean isEveryoneHappy();
}
</programlisting>
   </informalexample>
   <para>
      The
      <code>@Remote</code>
      annotation tells Errai that we'd like to use this interface as a remote interface. The remote interface must be part of of the GWT client code. It cannot be part of the server-side code, since the interface will need to be referenced from both the client and server side code. That said, the implementation of a service is relatively simple to the point:
    </para>
   <informalexample>
      <programlisting language="java">
@Service
public class MyRemoteServiceImpl implements MyRemoteService {

  public boolean isEveryoneHappy() {
    // blatently lie and say everyone's happy.
    return true;
  }
}
</programlisting>
   </informalexample>
   <para>
      That's all there is to it. You use the same
      <code>@Service</code>
      annotation as described in Section 2.4. The presence of the remote interface tips Errai off as to what you want to do with the class.
    </para>
   <section id="sid-5931313_RemoteProcedureCalls%28RPC%29-Makingcalls">
      <title>Making calls</title>
      <para>
        Calling a remote service involves use of the
        <code>MessageBuilder</code>
        API. Since all messages are asynchronous, the actual code for calling the remote service involves the use of a callback, which we use to receive the response from the remote method. Let's see how it works:
      </para>
      <informalexample>
         <programlisting language="java">
MessageBuilder.createCall(new RemoteCallback&lt;Boolean&gt;() {
  public void callback(Boolean isHappy) {
    if (isHappy) Window.alert("Everyone is happy!");
  }
 }, MyRemoteService.class).isEveryoneHappy();
</programlisting>
      </informalexample>
      <para>
        In the above example, we declare a remote callback that receives a Boolean, to correspond to the return value of the method on the server. We also reference the remote interface we are calling, and directly call the method. However,
        <emphasis role="italics">don't be tempted to write code like this</emphasis>
        :
      </para>
      <informalexample>
         <programlisting language="java">
 boolean bool = MessageBuilder.createCall(..., MyRemoteService.class).isEveryoneHappy();
</programlisting>
      </informalexample>
      <para>The above code will never return a valid result. In fact, it will always return null, false, or 0 depending on the type. This is due to the fact that the method is dispatched asynchronously, as in, it does not wait for a server response before returning control. The reason we chose to do this, as opposed to emulate the native GWT-approach, which requires the implementation of remote and async interfaces, was purely a function of a tradeoff for simplicity.</para>
      <section id="sid-5931313_RemoteProcedureCalls%28RPC%29-ProxyInjection">
         <title>Proxy Injection</title>
         <para>
          An alternative to using the
          <code>MessageBuilder</code>
          API is to have a proxy of the service injected.
        </para>
         <informalexample>
            <programlisting language="java">
@Inject
private Caller&lt;MyRemoteService&gt; remoteService; 
</programlisting>
         </informalexample>
         <para>
          For calling the remote service, the callback objects need to be provided to the
          <code>call</code>
          method before the corresponding interface method is invoked.
        </para>
         <informalexample>
            <programlisting language="java">
remoteService.call(callback).isEveryoneHappy();
</programlisting>
         </informalexample>
      </section>
   </section>
   <section id="sid-5931313_RemoteProcedureCalls%28RPC%29-Handlingexceptions">
      <title>Handling exceptions</title>
      <para>
        Handling remote exceptions can be done by providing an
        <code>ErrorCallback</code>
        on the client:
      </para>
      <informalexample>
         <programlisting language="java">
MessageBuilder.createCall(
  new RemoteCallback&lt;Boolean&gt;() {
    public void callback(Boolean isHappy) {
      if (isHappy) Window.alert("Everyone is happy!");
    }
  },
  new ErrorCallback() {
    public boolean error(Message message, Throwable caught) {
      try {
        throw caught;
      }
      catch (NobodyIsHappyException e) {
        Window.alert("OK, that's sad!");
      }
      catch (Throwable t) {
        GWT.log("An unexpected error has occurred", t);
      }
      return false;
    }
  },
  MyRemoteService.class).isEveryoneHappy();
</programlisting>
      </informalexample>
      <para>
        As remote exceptions need to be serialized to be sent to the client, the
        <code>@Portable</code>
        annotation needs to be present on the corresponding exception class (see
        <xref linkend="sid-5931328"/>
        ). Further the exception class needs to be part of the client-side code. For more details on
        <code>ErrorCallbacks</code>
        see
        <xref linkend="sid-5931306"/>
        .
      </para>
   </section>
   <section id="sid-5931313_RemoteProcedureCalls%28RPC%29-ClientsideInterceptors">
      <title>Client-side Interceptors</title>
      <para>Client-side remote call interceptors provide the ability to manipulate or bypass the remote call before it's being sent. This is useful for implementing crosscutting concerns like caching, for example when the remote call should be avoided if the data is already cached locally.</para>
      <para>
        To have a remote call intercepted, either an interface method or the remote interface type has to be annotated with
        <code>@InterceptedCall</code>
        . If the type is annotated, all interface methods will be intercepted.
      </para>
      <informalexample>
         <programlisting language="java">
@Remote
public interface CustomerService {

  @InterceptedCall(MyCacheInterceptor.class)
  public Customer retrieveCustomerById(long id);
}
</programlisting>
      </informalexample>
      <para>Note that an ordered list of interceptors can be used for specifying an interceptor chain e.g.</para>
      <informalexample>
         <programlisting language="java">
@InterceptedCall({MyCacheInterceptor.class, MySecurityInterceptor.class})
public Customer retrieveCustomerById(long id);
</programlisting>
      </informalexample>
      <para>Implementing an interceptor is easy:</para>
      <informalexample>
         <programlisting language="java">
public class MyCacheInterceptor implements RpcInterceptor {

  @Override
  public void aroundInvoke(final RemoteCallContext context) {
    // e.g check if the result is cached and carry out the actual call only in case it's not.
    context.proceed() // executes the next interceptor in the chain or the actual remote call.
    // context.setResult() // sets the result directly without carrying out the remote call.
  }
}
</programlisting>
      </informalexample>
      <para>
        The
        <code>RemoteCallContext</code>
        passed to the
        <code>aroundInvoke</code>
        method provides access to the intercepted method's name and read/write access to the parameter values provided at the call site.
      </para>
      <para>
        Calling
        <code>proceed</code>
        executes the next interceptor in the chain or the actual remote call if all interceptors have already been executed. If access to the result of the (asynchronous) remote call is needed in the interceptor, one of the overloaded versions of
        <code>proceed</code>
        accepting a
        <code>RemoteCallback</code>
        has to be used instead.
      </para>
      <para>
        The result of the remote call can be manipulated by calling
        <code>RemoteCallContext.setResult()</code>
      </para>
      <para>
        Not calling
        <code>proceed</code>
        in the interceptor bypasses the actual remote call, passing
        <code>RestCallContext.getResult()</code>
        to the
        <code>RemoteCallBack</code>
        provided at the call site.
      </para>
   </section>
   <section id="sid-5931313_RemoteProcedureCalls%28RPC%29-SessionandrequestobjectsinRPCendpoints">
      <title>Session and request objects in RPC endpoints</title>
      <para>
        Before invoking an endpoint method Errai sets up an
        <code>RpcContext</code>
        that provides access to message resources that are otherwise not visible to RPC endpoints.
      </para>
      <informalexample>
         <programlisting language="java">
@Service
public class MyRemoteServiceImpl implements MyRemoteService {

  public boolean isEveryoneHappy() {
    HttpSession session = RpcContext.getHttpSession();
    ServletRequest request = RpcContext.getServletRequest();
    ...
    return true;
  }
}
</programlisting>
      </informalexample>
   </section>
</chapter>
