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

Z FI WIKI
Přejít na: navigace, hledání
(REST server)
(REST server)
 
(Není zobrazeno 5 mezilehlých verzí od stejného uživatele.)
Řádka 586: Řádka 586:
 
     </properties>
 
     </properties>
 
     <dependencies>
 
     <dependencies>
         <!- Jackson JSON processor -->
+
         <!-- Jackson JSON processor -->
 
         <dependency>
 
         <dependency>
 
             <groupId>com.fasterxml.jackson.core</groupId>
 
             <groupId>com.fasterxml.jackson.core</groupId>
Řádka 633: Řádka 633:
 
Vytvořte si nový servlet
 
Vytvořte si nový servlet
 
<java>
 
<java>
/*
+
package cz.muni.fi.pa165.mavenproject2;
* To change this template, choose Tools | Templates
+
* and open the template in the editor.
+
*/
+
package cz.muni.fi.pa165.rest.server;
+
  
 
import com.fasterxml.jackson.databind.JsonNode;
 
import com.fasterxml.jackson.databind.JsonNode;
 
import com.fasterxml.jackson.databind.ObjectMapper;
 
import com.fasterxml.jackson.databind.ObjectMapper;
 
import org.apache.taglibs.standard.functions.Functions;
 
import org.apache.taglibs.standard.functions.Functions;
+
 
 
import javax.servlet.ServletException;
 
import javax.servlet.ServletException;
 
import javax.servlet.annotation.WebServlet;
 
import javax.servlet.annotation.WebServlet;
Řádka 652: Řádka 648:
 
import java.text.SimpleDateFormat;
 
import java.text.SimpleDateFormat;
 
import java.util.*;
 
import java.util.*;
+
 
 
@WebServlet(urlPatterns = "/tabule/*")
 
@WebServlet(urlPatterns = "/tabule/*")
 
public class TabuleServlet extends HttpServlet {
 
public class TabuleServlet extends HttpServlet {
+
 
     List<Map<String, String>> zaznamy = Collections.synchronizedList(new ArrayList<Map<String, String>>());
+
     final List<Map<String, String>> zaznamy = Collections.synchronizedList(new ArrayList<Map<String, String>>());
 
     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
 
 
     @Override
 
     @Override
 
     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Řádka 671: Řádka 667:
 
                 PrintWriter out = response.getWriter();
 
                 PrintWriter out = response.getWriter();
 
                 response.setHeader("Refresh", "5");
 
                 response.setHeader("Refresh", "5");
                 out.println("<h1>Tabule na "+request.getContextPath()+"/tabule</h2>");
+
                 out.println("<h1>Tabule na " + request.getContextPath() + "/tabule</h2>");
 
                 out.println("<table border=\"1\">");
 
                 out.println("<table border=\"1\">");
                 for (Map<String, String> m : zaznamy) {
+
                 synchronized (zaznamy) {
                    out.println("<tr><td>" + m.get("kdy") + "<td>" + m.get("kdo") + "<td>" + Functions.escapeXml(m.get("co")));
+
                    for (int i = zaznamy.size(); --i >= 0;) {
 +
                        Map<String, String> m = zaznamy.get(i);
 +
                        out.println("<tr><td><a href=\""+request.getContextPath()+"/tabule/"+i+"\">" + i + "</a>"
 +
                                + "<td>" + m.get("kdy")
 +
                                + "<td>" + m.get("kdo") + "<td>" + Functions.escapeXml(m.get("co")));
 +
                    }
 
                 }
 
                 }
 
                 out.println("</table>");
 
                 out.println("</table>");
Řádka 684: Řádka 685:
 
         }
 
         }
 
     }
 
     }
+
 
 
     @Override
 
     @Override
 
     protected synchronized void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
     protected synchronized void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Řádka 694: Řádka 695:
 
             m.put("kdo", request.getRemoteHost());
 
             m.put("kdo", request.getRemoteHost());
 
             m.put("co", zverejni);
 
             m.put("co", zverejni);
             zaznamy.add(0,m);
+
             zaznamy.add(m);
 
             response.sendRedirect(request.getContextPath() + "/tabule/" + (zaznamy.size() - 1));
 
             response.sendRedirect(request.getContextPath() + "/tabule/" + (zaznamy.size() - 1));
 
         } else if (request.getContentType().startsWith("application/json")) {
 
         } else if (request.getContentType().startsWith("application/json")) {
Řádka 705: Řádka 706:
 
                 m.put("kdo", request.getRemoteHost());
 
                 m.put("kdo", request.getRemoteHost());
 
                 m.put("co", jsonZverejni.textValue());
 
                 m.put("co", jsonZverejni.textValue());
                 zaznamy.add(0,m);
+
                 zaznamy.add(m);
 
                 response.sendRedirect(request.getContextPath() + "/tabule/" + (zaznamy.size() - 1));
 
                 response.sendRedirect(request.getContextPath() + "/tabule/" + (zaznamy.size() - 1));
 
             } else {
 
             } else {
Řádka 717: Řádka 718:
 
     }
 
     }
 
}
 
}
 
 
</java>
 
</java>
  
Řádka 769: Řádka 769:
 
import com.fasterxml.jackson.databind.JsonNode;
 
import com.fasterxml.jackson.databind.JsonNode;
 
import org.springframework.web.client.RestTemplate;
 
import org.springframework.web.client.RestTemplate;
 
+
 
import java.net.URI;
 
import java.net.URI;
 
+
import java.util.HashMap;
 +
import java.util.Map;
 +
 
public class TabuleRestKlient {
 
public class TabuleRestKlient {
 
+
   
 +
    static String STROJ = "localhost";
 +
    static int PORT = 8080;
 +
    static String webapp = "rest-tabule-server";
 +
   
 
     public static void main(String[] args) {
 
     public static void main(String[] args) {
 
         RestTemplate rt = new RestTemplate();
 
         RestTemplate rt = new RestTemplate();
 
+
 +
        String url = "http://"+STROJ+":"+PORT+"/"+webapp+"/tabule";
 +
       
 
         //POST pro přidání
 
         //POST pro přidání
         URI uri = rt.postForLocation("http://localhost:8080/tabule/?zverejni={text}", null, "příliš žlutoučký kůň");
+
         URI uri = rt.postForLocation(url+"?zverejni={text}", null, "příliš žluťoučký kůň");
 
+
 
         System.out.println("uri nového záznamu = " + uri);
 
         System.out.println("uri nového záznamu = " + uri);
 
+
 
         //GET pro získání všech záznamů
 
         //GET pro získání všech záznamů
         JsonNode jsonNode = rt.getForObject("http://localhost:8080/tabule/", JsonNode.class);
+
         JsonNode jsonNode = rt.getForObject(url, JsonNode.class);
 
+
 
         for(JsonNode m : jsonNode) {
 
         for(JsonNode m : jsonNode) {
 
             System.out.println("záznam = " + m);
 
             System.out.println("záznam = " + m);
Řádka 804: Řádka 811:
 
         Map<String,String> map = new HashMap<String, String>();
 
         Map<String,String> map = new HashMap<String, String>();
 
         map.put("zverejni","příliš žlutoučká kráva");
 
         map.put("zverejni","příliš žlutoučká kráva");
         URI uri = rt.postForLocation("http://localhost:8080/tabule", map);
+
         URI uri = rt.postForLocation(url, map);
  
 
</java>
 
</java>

Aktuální verze z 4. 12. 2012, 19:10


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, tak z příkazového řádku se to udělá takto:

 
  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'
  

nebo v NetBeans si vytvoříte nový projekt pomocí File - New Project - Categories: Java - Projects: Java Application, v dialogu 'Create Main Class zadat cz.muni.fi.pa165.rmi.Pisalek, pak v Libraries zvolit Add JAR/Folder, přidat soubor tabule.jar, přepsat třídu Pisalek, na projektu pak zvolit Properties - Run - Arguments a do políčka napsat nymfe31 'neco chytreho' . Pak spustit projekt. Z příkazové řádky je to jednodušší, že. )

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 zkompilována

javac -cp tabule.jar:. cz/muni/fi/pa165/rmi/TabuleImpl.java

a 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

Pozor, v B130 v listopadu 2012 je nesmyslně zkonfigurovaný /etc/hosts, váže název stroje na lokální adresu, takže nelze kontaktovat jiné stroje přes RMI. Proto je potřeba použít následující:

MYADDR=`ifconfig | awk -F':' '/inet addr/&&!/127.0.0.1/{split($2,_," ");print _[1]}'`
echo $MYADDR
java -Djava.rmi.server.codebase=http://acrab.ics.muni.cz/~makub/rmi/tabule.jar \
 -Djava.rmi.server.hostname=$MYADDR -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.

JSON-RPC

Ukážeme si vzdálené volání procedur (RPC) pomocí protokolu JSON-RPC 2.0. K implementaci použijeme knihovnu jsonrpc4j.


Rozhraní služby

Stáhněte si Mavenový projekt tabule-json-rpc.zip, rozzipujte, a nainstalujte, bud pomocí mvn install nebo otevřením v NetBeans a zvolením Build.

Projekt obsahuje definici rozhraní a vyjímky:

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);
    }
 
}

JSON-RPC server

Vytvořte si nový projekt typu Maven s názvem tabule-json-rpc-server a do pom.xml připište závislost na projektu tabule-json-rpc a knihovnách pro JSON-RPC:

 
    <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>cz.muni.fi.pa165</groupId>
            <artifactId>tabule-json-rpc</artifactId>
            <version>1.0</version>
        </dependency>
        <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:

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 java.io.IOException;
import java.net.InetSocketAddress;
import java.util.logging.*;
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;
 
public class SimpleServer implements Container {
 
    private JsonRpcServer jsonRpcServer;
    
    public SimpleServer(JsonRpcServer jsonRpcServer) {
        this.jsonRpcServer = jsonRpcServer;
    }
 
    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 {
        //enable logging
        Logger log = LogManager.getLogManager().getLogger("");
        log.setLevel(Level.ALL);
        for (Handler h : log.getHandlers()) h.setLevel(Level.FINEST);
        //start server
        Logger.getLogger(SimpleServer.class.getName()).info("starting server");
        JsonRpcServer tabule = new JsonRpcServer(new TabuleImpl(), Tabule.class);
        Connection connection = new SocketConnection(new SimpleServer(tabule));
        connection.connect(new InetSocketAddress(1420));
    }
 
}

Spusťte server.

JSON-RPC klient

Vytvořte nový projekt typu Maven jménem tabule-json-rpc-klient 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>cz.muni.fi.pa165</groupId>
            <artifactId>tabule-json-rpc</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>com.googlecode</groupId>
            <artifactId>jsonrpc4j</artifactId>
            <version>0.25</version>
        </dependency>
    </dependencies>

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("ahoj");
        //tabule.zverejni(null);
    }
}

Spusťte klienta. Pak zkuste odkomentovat řádek s tabule.zverejni(null); a spusťte ho znovu.

Samostatný úkol - změna rozhraní

V původním projektu tabule-json-rpc přidejte do rozhraní Tabule nějakou další metodu, dejte Build.

V projektu tabule-json-rpc-server implementujte metodu ve třídě TabuleImpl a znovu spusťte server.

V projektu tabule-json-rpc-klient zavolejte novou metodu.

Pozorujte, jak vypadají JSON-RPC zprávy v logu serveru.

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>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <cxf.version>2.7.0</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>
        <!-- SLF4J binding -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jdk14</artifactId>
            <version>1.7.2</version>
        </dependency>
    </dependencies>

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>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <cxf.version>2.7.0</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>2.5.6</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>
                <version>2.5.1</version>
                <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");
            System.out.println("zaslano"); 
            
            //tabule.zverejni("");
 
        } catch (Vyjimka_Exception e) {
            e.printStackTrace();
            System.out.println(e.getFaultInfo().getDuvod());
        }
    }
}

V NetBeans dejte Build. 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");

REST

REST server

Vytvořte si nový projekt typu Maven - Web Application, jménem třeba rest-tabule-server.

Do pom.xml připište:

 
<packaging>war</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <dependencies>
        <!-- Jackson JSON processor -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.1.1</version>
        </dependency>
        <!-- servlet API 3.0 -->
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- JSTL , just for escaping HTML -->
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <!-- Java language version -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
            <!-- Servlet 3.0 without web.xml -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.1.1</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>

Vytvořte si nový servlet

 
package cz.muni.fi.pa165.mavenproject2;
 
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.taglibs.standard.functions.Functions;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.*;
 
@WebServlet(urlPatterns = "/tabule/*")
public class TabuleServlet extends HttpServlet {
 
    final List<Map<String, String>> zaznamy = Collections.synchronizedList(new ArrayList<Map<String, String>>());
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String pathInfo = request.getPathInfo();
        if (pathInfo != null && pathInfo.matches("/\\d+")) {
            response.setContentType("application/json");
            ObjectMapper mapper = new ObjectMapper();
            mapper.writeValue(response.getOutputStream(), zaznamy.get(Integer.parseInt(pathInfo.substring(1))));
        } else {
            if ("html".equals(request.getParameter("type"))) {
                response.setContentType("text/html;charset=utf-8");
                PrintWriter out = response.getWriter();
                response.setHeader("Refresh", "5");
                out.println("<h1>Tabule na " + request.getContextPath() + "/tabule</h2>");
                out.println("<table border=\"1\">");
                synchronized (zaznamy) {
                    for (int i = zaznamy.size(); --i >= 0;) {
                        Map<String, String> m = zaznamy.get(i);
                        out.println("<tr><td><a href=\""+request.getContextPath()+"/tabule/"+i+"\">" + i + "</a>"
                                + "<td>" + m.get("kdy")
                                + "<td>" + m.get("kdo") + "<td>" + Functions.escapeXml(m.get("co")));
                    }
                }
                out.println("</table>");
            } else {
                response.setContentType("application/json");
                ObjectMapper mapper = new ObjectMapper();
                mapper.writeValue(response.getOutputStream(), zaznamy);
            }
        }
    }
 
    @Override
    protected synchronized void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String zverejni = request.getParameter("zverejni");
        if (zverejni != null) {
            Map<String, String> m = new LinkedHashMap<String, String>();
            m.put("kdy", sdf.format(new Date()));
            m.put("kdo", request.getRemoteHost());
            m.put("co", zverejni);
            zaznamy.add(m);
            response.sendRedirect(request.getContextPath() + "/tabule/" + (zaznamy.size() - 1));
        } else if (request.getContentType().startsWith("application/json")) {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode jsonNode = mapper.readValue(request.getInputStream(), JsonNode.class);
            JsonNode jsonZverejni = jsonNode.get("zverejni");
            if (!jsonNode.isMissingNode()) {
                Map<String, String> m = new LinkedHashMap<String, String>();
                m.put("kdy", sdf.format(new Date()));
                m.put("kdo", request.getRemoteHost());
                m.put("co", jsonZverejni.textValue());
                zaznamy.add(m);
                response.sendRedirect(request.getContextPath() + "/tabule/" + (zaznamy.size() - 1));
            } else {
                System.err.println("Missing key");
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing required data key.");
            }
        } else {
            System.err.println("Unknown request type " + request.getContentType());
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Unknown request type.");
        }
    }
}

Po spuštění by na URL http://localhost:8080/tabule/?type=html měla být viditelná HTMl verze tabule, zatím prázdná. Na http://localhost:8080/tabule/ pak JSON data, zatím také prázdná.

REST klient

Vytvořte si nový projekt typu Maven - Java Application, jménem třeba rest-tabule-klient.

Do pom.xml připište

 
 <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
 
    <build>
        <plugins>
            <!-- Java language version -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>3.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.1.1</version>
        </dependency>
    </dependencies>

Vyvtořte si REST klienta, který přidá záznam a získá všechny záznamy:

 
package cz.muni.fi.pa165.rest.klient;
 
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.web.client.RestTemplate;
 
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
 
public class TabuleRestKlient {
    
    static String STROJ = "localhost";
    static int PORT = 8080;
    static String webapp = "rest-tabule-server";
    
    public static void main(String[] args) {
        RestTemplate rt = new RestTemplate();
 
        String url = "http://"+STROJ+":"+PORT+"/"+webapp+"/tabule";
        
        //POST pro přidání
        URI uri = rt.postForLocation(url+"?zverejni={text}", null, "příliš žluťoučký kůň");
        System.out.println("uri nového záznamu = " + uri);
 
        //GET pro získání všech záznamů
        JsonNode jsonNode = rt.getForObject(url, JsonNode.class);
 
        for(JsonNode m : jsonNode) {
            System.out.println("záznam = " + m);
        }
    }
}

Používáme Spring 3.x RestTemplate (javadoc pro RestTemplate).

Po spuštění na výše uvedeném URL můžete pozorovat přibývající záznamy.

Všimněte si, že kódování češtiny moc nefunguje, zkusíme to opravit.

Změníme kód klienta tak, aby místo URL parametru používal tělo POST requestu ve formátu JSON:

 
        //POST pro přidání
        Map<String,String> map = new HashMap<String, String>();
        map.put("zverejni","příliš žlutoučká kráva");
        URI uri = rt.postForLocation(url, map);