PA165/Cvičení Remoting: Porovnání verzí

Z FI WIKI
Přejít na: navigace, hledání
(AJAX a JSON)
(JSON-RPC)
Řádka 348: Řádka 348:
  
 
=== JSON-RPC ===
 
=== JSON-RPC ===
 +
 +
==== JSON-RPC server ====
  
 
Vytvořte si nový projekt typu [[Maven]]  a do pom.xml připište:
 
Vytvořte si nový projekt typu [[Maven]]  a do pom.xml připište:
Řádka 353: Řádka 355:
 
<xml>
 
<xml>
 
     <name>tabule-json-rpc-server</name>
 
     <name>tabule-json-rpc-server</name>
 
 
     <properties>
 
     <properties>
 
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 
     </properties>
 
     </properties>
 
 
     <repositories>
 
     <repositories>
 
         <repository>
 
         <repository>
Řádka 366: Řádka 366:
 
         </repository>
 
         </repository>
 
     </repositories>
 
     </repositories>
 
 
     <dependencies>
 
     <dependencies>
 
         <dependency>
 
         <dependency>
Řádka 378: Řádka 377:
 
             <version>2.0</version>
 
             <version>2.0</version>
 
             <scope>provided</scope>
 
             <scope>provided</scope>
 +
        </dependency>
 +
        <dependency>
 +
            <groupId>org.apache.tomcat</groupId>
 +
            <artifactId>tomcat-servlet-api</artifactId>
 +
            <version>7.0.27</version>
 
         </dependency>
 
         </dependency>
 
         <dependency>
 
         <dependency>
Řádka 387: Řádka 391:
 
</xml>
 
</xml>
  
 +
Vytvořte následující třídy v balíku '''cz.muni.fi.pa165.jsonrpc''':
 +
 +
'''Tabule.java'''
 +
<java>
 +
package cz.muni.fi.pa165.jsonrpc;
 +
 +
public interface Tabule {
 +
    void zverejni(String text) throws Vyjimka;
 +
}
 +
</java>
 +
'''Vyjimka.java'''
 +
<java>
 +
package cz.muni.fi.pa165.jsonrpc;
 +
 +
public class Vyjimka extends Exception {
 +
 +
    public Vyjimka(String message) {
 +
        super(message);
 +
    }
 +
 +
}
 +
</java>
 +
'''TabuleImpl.java'''
 +
<java>
 +
package cz.muni.fi.pa165.jsonrpc;
 +
 +
public class TabuleImpl implements Tabule {
 +
 +
    @Override
 +
    public void zverejni(String text) throws Vyjimka {
 +
        if (text == null || text.isEmpty()) throw new Vyjimka("text je prázdný");
 +
        System.out.println(SimpleServer.getClient()+": " + text);
 +
    }
 +
}
 +
</java>
 +
'''SimpleServer.java'''
 +
<java>
 +
package cz.muni.fi.pa165.jsonrpc;
 +
 +
import com.googlecode.jsonrpc4j.JsonRpcServer;
 +
import org.simpleframework.http.Request;
 +
import org.simpleframework.http.Response;
 +
import org.simpleframework.http.core.Container;
 +
import org.simpleframework.transport.connect.Connection;
 +
import org.simpleframework.transport.connect.SocketConnection;
 +
 +
import java.io.IOException;
 +
import java.net.InetSocketAddress;
 +
 +
public class SimpleServer implements Container {
 +
 +
    private JsonRpcServer jsonRpcServer = new JsonRpcServer(new TabuleImpl(), Tabule.class);
 +
    private static ThreadLocal<String> client = new ThreadLocal<String>();
 +
    static String getClient() {
 +
        return client.get();
 +
    }
 +
 +
    @Override
 +
    public void handle(Request request, Response response) {
 +
        try {
 +
            if ("POST".equals(request.getMethod())) {
 +
                response.set("Content-Type", "application/json");
 +
                client.set(request.getClientAddress().getHostName());
 +
                jsonRpcServer.handle(request.getInputStream(), response.getOutputStream());
 +
            }
 +
        } catch (IOException e) {
 +
            throw new RuntimeException(e);
 +
        }
 +
    }
 +
 +
    public static void main(String[] args) throws IOException {
 +
        System.out.println("starting server ...");
 +
        Connection connection = new SocketConnection(new SimpleServer());
 +
        connection.connect(new InetSocketAddress(1420));
 +
    }
 +
 +
}
 +
</java>
 +
 +
Spusťte server.
 +
 +
==== JSON-RPC klient ====
 +
 +
Vytvořte nový projekt typu Maven a do pom.xml připište:
 +
<xml>
 +
<repositories>
 +
        <repository>
 +
            <id>jsonrpc4j-webdav-maven-repo</id>
 +
            <name>jsonrpc4j maven repository</name>
 +
            <url>http://jsonrpc4j.googlecode.com/svn/maven/repo/</url>
 +
            <layout>default</layout>
 +
        </repository>
 +
    </repositories>
 +
 +
    <dependencies>
 +
        <dependency>
 +
            <groupId>com.googlecode</groupId>
 +
            <artifactId>jsonrpc4j</artifactId>
 +
            <version>0.25</version>
 +
        </dependency>
 +
    </dependencies>
 +
</xml>
 +
 +
Okopírujte do něj třídy Tabule.java Vyjimka.java. Pak vytvořte třídu
 +
 +
'''SimpleClient.java'''
 +
<java>
 +
package cz.muni.fi.pa165.jsonrpc;
 +
 +
import com.googlecode.jsonrpc4j.JsonRpcHttpClient;
 +
import com.googlecode.jsonrpc4j.ProxyUtil;
 +
 +
import java.net.MalformedURLException;
 +
import java.net.URL;
 +
 +
public class SimpleClient {
 +
 +
    public static void main(String[] args) throws MalformedURLException, Vyjimka {
 +
 +
        JsonRpcHttpClient client = new JsonRpcHttpClient(new URL("http://localhost:1420/"));
 +
        Tabule tabule = ProxyUtil.createClientProxy(SimpleClient.class.getClassLoader(), Tabule.class, client);
 +
 +
        tabule.zverejni(null);
 +
    }
 +
}
 +
</java>
 +
 +
Spusťte klienta.
  
 
=== AJAX ===
 
=== AJAX ===
  
 
viz [[Cvičení AJAX]].
 
viz [[Cvičení AJAX]].

Verze z 9. 11. 2012, 19:04


JavaRMI

Nejdřív si předvedeme JavaRMI.

Na tabule.jar je JAR soubor s následující definicí:

 
package cz.muni.fi.pa165.rmi;
 
import java.rmi.Remote;
import java.rmi.RemoteException;
 
public interface Tabule extends Remote {
 
    void zverejni(String text) throws RemoteException;
    
}

Klient

Vytvořte si projekt, přidejte k němu JAR s rozhraním a vytvořte klienta:

 
package cz.muni.fi.pa165.rmi;
 
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.NotBoundException;
 
public class Pisalek {
 
    public static void main(String[] args) throws RemoteException, NotBoundException {
        if(args.length!=2) {
            System.out.println("Usage: java "+Pisalek.class.getName()+" host text");
            System.exit(1);
        }
        String host = args[0];
        String text = args[1];
 
        Registry remregistry = LocateRegistry.getRegistry(host);
        Tabule tabule = (Tabule) remregistry.lookup("tabule");
 
        tabule.zverejni(text);
    }
}

Klienta spusťte vůči serveru cvičícího na nymfe31.fi.muni.cz.


(Pro ty, kdo neumí zkompilovat a spustit javovou třídu:

 
  mkdir rmicviceni
  cd rmicviceni
  wget http://acrab.ics.muni.cz/~makub/rmi/tabule.jar
  mkdir -p cz/muni/fi/pa165/rmi
  vi cz/muni/fi/pa165/rmi/Pisalek.java
  javac -cp tabule.jar:. cz/muni/fi/pa165/rmi/Pisalek.java
  java -cp tabule.jar:. cz.muni.fi.pa165.rmi.Pisalek nymfe31 'neco chytreho'
  

)

Server

Utvořte dvojice se sousedem a vyzkoušejte komunikaci s jeho serverem.

Na straně serveru je třeba spustit na pozadí program

rmiregistry &

mít implementaci serveru:

 
package cz.muni.fi.pa165.rmi;
 
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.ServerNotActiveException;
import java.rmi.server.UnicastRemoteObject;
 
public class TabuleImpl implements Tabule {
 
    synchronized public void zverejni(String text) throws RemoteException {
        try {
            System.out.println(UnicastRemoteObject.getClientHost() + ": " + text);
        } catch (ServerNotActiveException e) {
            e.printStackTrace();
        }
    }
 
    public static void main(String[] args) throws RemoteException {
        System.out.println("startuji Tabuli");
        Tabule stub = (Tabule) UnicastRemoteObject.exportObject(new TabuleImpl(), 0);
        LocateRegistry.getRegistry().rebind("tabule", stub);
    }
 
}

která musí být spuštěna se správnými parametry:

java -Djava.rmi.server.codebase=http://acrab.ics.muni.cz/~makub/rmi/tabule.jar -cp tabule.jar:.  cz.muni.fi.pa165.rmi.TabuleImpl

Metoda v rozhraní Tabule nepřijímá žádné třídy, které by JVM na straně serveru neznal. Pokud by tomu tak bylo, i klient by musel vystavit takové třídy někde na webu a musel by být spuštěn s parametrem -Djava.rmi.server.codebase, aby si server mohl třídy stáhnout.

SOAP/WSDL Web Services

Ukážeme si web services pomocí Apache CXF.


SOAP server

Vytvořte si nový projekt typu Maven zvaný třeba soap-cxf-server. Do pom.xml připište:

 
   <properties>
        <cxf.version>2.2.4</cxf.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <!-- Jetty is needed if you're are not using the CXFServlet -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>${cxf.version}</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- nastaveni verze zdrojaku -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

Vytvořte package cz.muni.fi.pa165.soap a v něm tyto třídy:

 
package cz.muni.fi.pa165.soap;
 
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.ws.WebFault;
 
@WebFault(name = "Vyjimka")
@XmlAccessorType(XmlAccessType.FIELD)
public class Vyjimka extends RuntimeException {
    String duvod;
 
    public Vyjimka(String message,String duvod) {
        super(message);
        this.duvod = duvod;
    }
}
 
package cz.muni.fi.pa165.soap;
 
import javax.jws.WebService;
import javax.jws.WebParam;
 
@WebService
public interface Tabule {
    
    void zverejni(@WebParam(name = "text")String text) throws Vyjimka;
 
}
 
package cz.muni.fi.pa165.soap;
 
import javax.annotation.Resource;
import javax.jws.WebService;
import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
 
@WebService(endpointInterface = "cz.muni.fi.pa165.soap.Tabule", serviceName = "Tabule")
public class TabuleImpl implements Tabule {
 
    @Resource
    WebServiceContext wsCtx;
 
    public void zverejni(String text) throws Vyjimka {
        if (text == null || text.isEmpty()) throw new Vyjimka("empty text", "retezec prazdny");
 
        System.out.println(getClient() + ":" + text);
    }
 
    private String getClient() {
        MessageContext msgCtx = wsCtx.getMessageContext();
        HttpServletRequest req = (HttpServletRequest) msgCtx.get(MessageContext.SERVLET_REQUEST);
        return req.getRemoteHost();
    }
 
}
 
package cz.muni.fi.pa165.soap;
 
import javax.xml.ws.Endpoint;
 
public class Server {
    public static void main(String[] args) throws InterruptedException {
        String address = "http://localhost:9000/tabule";
        Endpoint.publish(address, new TabuleImpl());
        System.out.println("Server ready...");
    }
}

Spusťte třídu cz.muni.fi.pa165.soap.Server a navštivte URL http://localhost:9000/tabule?wsdl.


SOAP klient

Aniž uzavřete předchozí projekt, vytvořte nový projekt zvaný třeba soap-cxf-klient. Děláme to tak proto, abychom viděli, že jediným pojítkem mezi serverem a klientem je WSDL popis služby.

Do pom.xml připište

 
    <properties>
        <cxf.version>2.2.4</cxf.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-common-utilities</artifactId>
            <version>${cxf.version}</version>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>${cxf.version}</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <configuration>
                            <wsdlOptions>
                                <wsdlOption>
                                    <wsdl>http://localhost:9000/tabule?wsdl</wsdl>
                                </wsdlOption>
                            </wsdlOptions>
                        </configuration>
                        <goals>
                            <goal>wsdl2java</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
 
            <!-- nastaveni verze zdrojaku -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
            <!-- zavislosti na JARech -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <configuration>
                    <outputDirectory>
                        ${project.build.directory}
                    </outputDirectory>
                </configuration>
            </plugin>
        </plugins>
    </build>

Přidejte třídu:

 
package cz.muni.fi.pa165.soap;
 
public class Klient {
    public static void main(String[] args) {
        Tabule tabule = new Tabule_Service().getTabuleImplPort();
        try {
            
            tabule.zverejni("ahoj");
 
            tabule.zverejni("");
 
        } catch (Vyjimka_Exception e) {
            e.printStackTrace();
            System.out.println(e.getFaultInfo().getDuvod());
        }
    }
}

Klikněte pravým tlačítkem a vyberte Maven - Update folders. Alternativně můžete z příkazového řádku spustit mvn generate-sources a mvn package.

Spusťte třídu Klient.

Pro kopii všech knihoven potřebných pro spuštění z příkazového řádku zadejte příkaz mvn dependency:copy-dependencies.

URL na službu se bere z WSDL popisu služby. Pokud ho potřebujete změnit, lze to udělat takto:

 
((BindingProvider) tabule).getRequestContext()
                .put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://nymfe31.fi.muni.cz:9000/tabule");

JSON-RPC

JSON-RPC server

Vytvořte si nový projekt typu Maven a do pom.xml připište:

 
    <name>tabule-json-rpc-server</name>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <repositories>
        <repository>
            <id>jsonrpc4j-webdav-maven-repo</id>
            <name>jsonrpc4j maven repository</name>
            <url>http://jsonrpc4j.googlecode.com/svn/maven/repo/</url>
            <layout>default</layout>
        </repository>
    </repositories>
    <dependencies>
        <dependency>
            <groupId>com.googlecode</groupId>
            <artifactId>jsonrpc4j</artifactId>
            <version>0.25</version>
        </dependency>
        <dependency>
            <groupId>javax.portlet</groupId>
            <artifactId>portlet-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-servlet-api</artifactId>
            <version>7.0.27</version>
        </dependency>
        <dependency>
            <groupId>org.simpleframework</groupId>
            <artifactId>simple</artifactId>
            <version>4.1.21</version>
        </dependency>
    </dependencies>

Vytvořte následující třídy v balíku cz.muni.fi.pa165.jsonrpc:

Tabule.java

 
package cz.muni.fi.pa165.jsonrpc;
 
public interface Tabule {
    void zverejni(String text) throws Vyjimka;
}

Vyjimka.java

 
package cz.muni.fi.pa165.jsonrpc;
 
public class Vyjimka extends Exception {
 
    public Vyjimka(String message) {
        super(message);
    }
 
}

TabuleImpl.java

 
package cz.muni.fi.pa165.jsonrpc;
 
public class TabuleImpl implements Tabule {
 
    @Override
    public void zverejni(String text) throws Vyjimka {
        if (text == null || text.isEmpty()) throw new Vyjimka("text je prázdný");
        System.out.println(SimpleServer.getClient()+": " + text);
    }
}

SimpleServer.java

 
package cz.muni.fi.pa165.jsonrpc;
 
import com.googlecode.jsonrpc4j.JsonRpcServer;
import org.simpleframework.http.Request;
import org.simpleframework.http.Response;
import org.simpleframework.http.core.Container;
import org.simpleframework.transport.connect.Connection;
import org.simpleframework.transport.connect.SocketConnection;
 
import java.io.IOException;
import java.net.InetSocketAddress;
 
public class SimpleServer implements Container {
 
    private JsonRpcServer jsonRpcServer = new JsonRpcServer(new TabuleImpl(), Tabule.class);
    private static ThreadLocal<String> client = new ThreadLocal<String>();
    static String getClient() {
        return client.get();
    }
 
    @Override
    public void handle(Request request, Response response) {
        try {
            if ("POST".equals(request.getMethod())) {
                response.set("Content-Type", "application/json");
                client.set(request.getClientAddress().getHostName());
                jsonRpcServer.handle(request.getInputStream(), response.getOutputStream());
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
 
    public static void main(String[] args) throws IOException {
        System.out.println("starting server ...");
        Connection connection = new SocketConnection(new SimpleServer());
        connection.connect(new InetSocketAddress(1420));
    }
 
}

Spusťte server.

JSON-RPC klient

Vytvořte nový projekt typu Maven a do pom.xml připište:

 
<repositories>
        <repository>
            <id>jsonrpc4j-webdav-maven-repo</id>
            <name>jsonrpc4j maven repository</name>
            <url>http://jsonrpc4j.googlecode.com/svn/maven/repo/</url>
            <layout>default</layout>
        </repository>
    </repositories>
 
    <dependencies>
        <dependency>
            <groupId>com.googlecode</groupId>
            <artifactId>jsonrpc4j</artifactId>
            <version>0.25</version>
        </dependency>
    </dependencies>

Okopírujte do něj třídy Tabule.java Vyjimka.java. Pak vytvořte třídu

SimpleClient.java

 
package cz.muni.fi.pa165.jsonrpc;
 
import com.googlecode.jsonrpc4j.JsonRpcHttpClient;
import com.googlecode.jsonrpc4j.ProxyUtil;
 
import java.net.MalformedURLException;
import java.net.URL;
 
public class SimpleClient {
 
    public static void main(String[] args) throws MalformedURLException, Vyjimka {
 
        JsonRpcHttpClient client = new JsonRpcHttpClient(new URL("http://localhost:1420/"));
        Tabule tabule = ProxyUtil.createClientProxy(SimpleClient.class.getClassLoader(), Tabule.class, client);
 
        tabule.zverejni(null);
    }
}

Spusťte klienta.

AJAX

viz Cvičení AJAX.