Spring permette di "esporre" i propri servizi sotto forma di web services basati sullo standard JAX-RPC e anche di accedere a generici web services in maniera trasparente dal punto di vista del codice client. Si tratterà come sempre di gestire la configurazione di Spring, in modo che quest'ultimo "lavori" per noi dietro le quinte per consentirci un accesso ai servizi remoti alla stregua dei componenti locali.

Introduzione

Integrare delle funzionalità esterne all'ambito "locale" della propria applicazione è una necessità molto comune oggigiorno. L'ambiente in cui particolari servizi vivono può essere più o meno esteso. Può essere circoscritto a una singola applicazione, nel caso di Java una singola Java Virtual Machine, a una rete locale, a una rete geografica o nella prospettiva più larga a Internet. Le tecnologie utilizzate per "distribuire" dei servizi in uno di questi ambiti sono le più varie. Il fattore comune a queste tecnologie è quello di utilizzare un insieme di regole atto all'esecuzione di procedure remote, che si può sintetizzare nella sigla RPC (Remote Procedure Call). Java fornisce un suo protocollo per l'RPC, denominato RMI (Remote Method Invocation), che costituisce tra l'altro la base per la tecnologia EJB (Enterprise Java Beans). L'uso di RMI e della tecnologia EJB ha senso generalmente per reti locali, e normalmente lo scenario è quello di distribuire i componenti applicativi in un nodo specifico accessibile dai componenti di frontend. Rendere i propri servizi accessibili in Internet implica invece utilizzare come canale di comunicazione il protocollo HTTP, dato che esso permette di attraversare le protezioni firewall delle varie reti, presupposto per avere delle funzionalità integrabili con degli standard globali e perfettamente "delocalizzate".

Esistono alcune soluzioni che implementano l'RPC utilizzando l'HTTP, come per esempio l'Hessian, ma lo standard accettato universalmente oramai è il protocollo SOAP, basato su XML. I servizi basati su SOAP sono chiamati web services e nel mondo Java la tecnologia che implementa l'RPC basato su SOAP è la JAX-RPC. Spring fornisce un suo supporto per esporre e per integrare web services che dietro le quinte utilizza appunto lo standard JAX-RPC. Nel prossimo paragrafo verrà spiegato come esporre delle funzionalità sotto forma di web services, mentre nel successivo come accedere nella propria applicazione basata su Spring a dei generici web services "pubblicati" in un qualche nodo su Internet.

Distribuire dei servizi

Immaginiamo di avere la seguente interfaccia:

public interface MyService {
  public void doSomething();
}
public interface RemoteMyService extends Remote {
  public void doSomething() throws RemoteException;
}
public class MyServiceEndpoint extends ServletEndpointSupport implements RemoteMyService {
  private MyService myServ;

  protected void onInit() {
    this.myServ = (MyService) getWebApplicationContext().getBean("myService");
  }

  public void doSomething() throws RemoteException {
    myServ.doSomething();
  }
}
<bean id="myWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
  <property name="serviceInterface" value="mypackage.RemoteMyService"/>
  <property name="wsdlDocumentUrl" value="http://localhost:8080/myapp/services/myService?WSDL"/>
  <property name="namespaceUri" value="http://localhost:8080/myapp/services/myService"/>
  <property name="serviceName" value="MyService"/>
  <property name="portName" value="MyPort"/>
</bean>
<bean id="client" class="esempio.MyClient">
  ...
  <property name="service" ref="myWebService"/>
</bean>
public class MyClient {
  private RemoteMyService service;

  public void setService(RemoteMyService service) {
    this.service = service;
  }

  public void foo() {
    try {
      service.doSomething();
    } catch (RemoteException ex) {
      ...
    }
  }
}
<bean id="myWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
  <property name="serviceInterface">
    <value>esempio.MyService</value>
  </property>
  <property name="portInterface">
    <value>esempio.RemoteMyService</value>
  </property>
  ...
</bean>
public class MyClient {
  private MyService service;

  public void setService(MyService service) {
    this.service = service;
  }

  public void foo() {
    service.doSomething();
  }
}