<?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 to 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>@ExposeEntity</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-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 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>