Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Java RESTful Web Services

Java RESTful Web Services

How to build RESTful Web Services using JAX-RS and Glassfish.

D9e65f4b0af059ae9ba243c8c2265e4f?s=128

Jussi Pohjolainen

May 29, 2016
Tweet

More Decks by Jussi Pohjolainen

Other Decks in Technology

Transcript

  1. Java RESTful Web Services Jussi Pohjolainen

  2. Business Needs Flexibility • Hook up new partners and acquisitions

    • Enable reuse of existing systems and business logic • Integrate • Flexibility
  3. Technical Problems • Different languages and platforms • Integration is

    hard and costly • Scalability • Security
  4. Solution: Web Service • Web Service is a method of

    communication of two electronic devices over a network • Software function provided at a network address over a Web • There is no "official specification" for web services • Possible to identify two major classes 1. REST-complient Web Services 2. SOAP "Big" Web Services
  5. What is Web Service? • Web Service is request /

    response mechanism that allows client to access or modify data • It's machine to machine, not intented for the user • User uses web page via URL and receives HTML that the browser understands • http://openweathermap.org/find?q=Tampere • Computer app uses web service via URL and receives usually either XML or JSON • http://api.openweathermap.org/data/2.5/weather ?q=Tampere
  6. Web Service • Is available over the Internet or private

    Intranet • Uses usually either XML or JSON • XML is heavily used in in SOAP Web Services • Is not tied to any operating system or programming language • Is self-describing and discoverable
  7. XML vs JSON Trends

  8. SHORT INTRO TO W3C SOAP WEB SERVICES

  9. Web Services and XML • WSDL • XML file that

    describes the service • SOAP • Simple Object Access Protocol • XML Format for sending messages
  10. WSDL • Web Services Description Language (WSDL) describes a web

    service • Specifies the location of the service • Specifies the operations of the service • Is written in XML and it's W3C recommendation • Description how to the service is called, what parameter it expects, what data structures it returns.
  11. Description • WSDL describes services as collection of Ports (wsdl

    1.1) or Endpoints (wsdl 2.0) • Defines the address or connection point to web service - > HTTP URL string
  12. <definitions name="HelloService" > <message name="SayHelloRequest"> <part name="firstName" type="xsd:string"/> </message> <message

    name="SayHelloResponse"> <part name="greeting" type="xsd:string"/> </message> <portType name="Hello_PortType"> <operation name="sayHello"> <input message="tns:SayHelloRequest"/> <output message="tns:SayHelloResponse"/> </operation> </portType> <binding name="Hello_Binding" type="tns:Hello_PortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="sayHello"> <soap:operation soapAction="sayHello"/> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:helloservice" use="encoded"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:helloservice" use="encoded"/> </output> </operation> </binding> <service name="Hello_Service"> <documentation>WSDL File for HelloService</documentation> <port binding="tns:Hello_Binding" name="Hello_Port"> <soap:address location="http://www.examples.com/SayHello/" /> </port> </service> </definitions>
  13. Testing StockQuote • WSDL file • http://www.webservicex.net/stockquote.asmx?WSDL • Operation GetQuote

    • http://www.webservicex.net/stockquote.asmx?op=GetQuote
  14. Imitate Client

  15. Generating Simple Java Client • Java 6 includes wsimport as

    part of JAX-WS • Generates all necessary classes to contact the service! • Usage • wsimport -keep -verbose http://www.webservicex.net/stockquote.asmx?WSDL
  16. Client import net.webservicex.*; class Main { public static void main(String[]

    args) throws Exception { StockQuote sq = new StockQuote(); StockQuoteSoap soap = sq.getStockQuoteSoap(); System.out.println( soap.getQuote("aapl") ); } }
  17. SOAP • SOAP, simple object access protocol • Exchanging information

    between web services • Mandatory building blocks: • Envelope • Identifies the xml document as soap • Body • Call and response information • Usually SOAP envelope is transferred via HTTP
  18. HTTP Request POST POST /test/page.html HTTP/1.1 Host: server.com name1=value1

  19. HTTP Request GET GET /test/page.php?name1=value HTTP/1.1 Host: server.com

  20. HTTP Response HTTP/1.0 200 OK Date: Fri, 31 Dec 1999

    23:59:59 GMT Content-Type: text/html Content-Length: 1354 <html> <body> <h1>Web Page</h1> (more file contents) . . . </body> </html>
  21. HTTP Response HTTP/1.0 200 OK Date: Fri, 31 Dec 2015

    23:59:59 GMT Content-Type: image/png Content-Length: 1354 10100111010101010101001011111....
  22. HTTP Response HTTP/1.0 200 OK Date: Fri, 31 Dec 2015

    23:59:59 GMT Content-Type: text/xml Content-Length: 1354 <books><book>...</book></books>
  23. Soap 1.2 Client Message in HTTP POST /stockquote.asmx HTTP/1.1 Host:

    www.webservicex.net Content-Type: application/soap+xml; charset=utf-8 Content-Length: length <?xml version="1.0" encoding="utf-8"?> <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"> <soap12:Body> <GetQuote xmlns="http://www.webserviceX.NET/"> <symbol>aapl</symbol> </GetQuote> </soap12:Body> </soap12:Envelope>
  24. Soap 1.2 Server Response in HTTP HTTP/1.1 200 OK Content-Type:

    application/soap+xml; charset=utf-8 Content-Length: length <?xml version="1.0" encoding="utf-8"?> <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema- instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"> <soap12:Body> <GetQuoteResponse xmlns="http://www.webserviceX.NET/"> <GetQuoteResult>string</GetQuoteResult> </GetQuoteResponse> </soap12:Body> </soap12:Envelope>
  25. Disadvantages • XML can slow things down, because XML files

    can be big • SOAP Web Services can be tricky to implement • XML is not compatible with data models of programming languages • REST Architecture is replacing SOAP Web Services?
  26. RESTFUL WEB SERVICES

  27. RESTful Web Services • Representational State Transfer (REST) is architectural

    style with uniform interface using URIs • Resources are manipulated with fixed set of HTTP calls • replace (HTTP PUT), read (HTTP GET), add (HTTP POST) and delete (HTTP DELETE) • No need for SOAP
  28. Example (wikipedia)

  29. Resource • Any item of interest, in any format •

    Example URI • http://www.someapi.com/customers/1 • Can return data about client with ID 1 (either in XML or JSON) • Can also update/delete the customer with ID 1
  30. Example: REST + XML

  31. Example: REST + XML

  32. Example: REST + JSON

  33. RESTful Design • Identify entities / resources • Create URI

    to each resource • Categorize if resources are needed to view and/or update • All HTTP Get should be side-effect free • Put hyperlinks to resource representation to enable clients to drill down for more information • Specify the format of response data • Create documentation how to use the service
  34. Testing REST • When testing HTTP GET you can just

    use browser • For more complicated services, you can use tools called cURL: http://curl.haxx.se/ • Via command line you can create HTTP GET, POST, DELETE, PUT commands: • curl GET http://localhost:8080/rest/cars • curl POST –d "{brand: 'skoda'}" http://localhost:8080/rest/cars • curl DELETE http://localhost:8080/rest/cars/0
  35. EXERCISE

  36. JAVA RESTFUL TOOLS

  37. Oracle Java • Java SE 1.8 • Standard Edition •

    Java EE 7 • Enterprise Edition • Java ME (Symbian, S40/Asha) • Mobile Edition
  38. Java EE • Widely used enterprise computing platform • Extends

    Java SE • Lot of API Specs • RMI, Web Services, XML • Enterprise components • EJBs, Servlets, JSPs • Enterprise Apps run under a app server • Glassfish, JBoss, WebLogic, WebSphere ..
  39. GlassFish • Open Source application server project started by Sun

    Microsystems for Java EE • Reference implementation of Java EE • Supports • JAX-RS, EJB, JavaServer Faces / Pages, RMI, Servlets etc.. • Allows developers to create enterprise apps that are portable and scalable • Download • https://glassfish.java.net/download.html
  40. Install • Fetch the .zip, unzip it and place in

    some directory: c:\glassfish • Put c:\glassfish\glassfish4\bin to path • Start • asadmin start-domain • Mac OS X: sudo asadmin start-domain • Stop • asadmin stop-domain domain1 • Open admin – console • http://localhost:4848/common/index.jsf
  41. WAR • WAR (Web Application Archive) is a JAR file

    to be used to distribute collection of java servlets, xmls, htmls etc. • Must contain • /WEB-INF/web.xml • /WEB-INF/classes/SomeClass.class • web.xml defines the structure of your app. It's not needed in the most current versions of Java EE
  42. HelloServlet.java import java.io.*; import javax.servlet.http.*; import javax.servlet.*; import javax.servlet.annotation.*; @WebServlet("/helloworld")

    public class HelloServlet extends HttpServlet { public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { PrintWriter out = res.getWriter(); out.println("Hello, world!"); out.close(); } }
  43. Compile • Compile using Java EE libraries • Add needed

    .jar to classpath • classpath = where to find third-party classes • You can classpath when compiling • javac -classpath ".;/path/to/glassfish4/glassfish/modules/javax.ser vlet-api.jar" HelloServlet.java • Or add all Java EE libraries to classpath for easier access • set CLASSPATH = /path/to/glassfish4/glassfish/lib/*;/path/to/glass fish4/glassfish/modules/*
  44. Create war • Once you have • WEB-INF/web.xml • WEB-INF/classes/HelloServlet.class

    • Package these into war • jar -cf HelloServlet.war . • Deploy • asadmin deploy --force=true HelloServlet.war • Test on Browser: • http://localhost:8080/HelloServlet/helloworld • Test in CLI using CURL • curl -X GET http://localhost:8080/HelloServlet/helloworld
  45. Use ant for easy compile and deploy • It might

    get complicated to give previous commands each time you make changes to your code. • Use ant (or other) for easier compiling and deploying • Create build.xmlthat holds information how to compile, create war, deploy and test • For example • ant compile • ant war • ant deploy • ant test
  46. Project Structure Example project/ build.xml src/HelloServlet.java war/WEB-INF/classes/

  47. build.xml <project default="main"> <property name="war-name" value="app"/> <property name="glassfish-path" value="/path/to/glassfish4"/> <property

    name="url" value="http://localhost:8080/app/helloworld"/> <property name="display-app" value="cat"/> <path id="master-classpath"> <fileset dir="${glassfish-path}/glassfish/lib"> <include name="*.jar"/> </fileset> <fileset dir="${glassfish-path}/glassfish/modules"> <include name="*.jar"/> </fileset> <pathelement path="${build.dir}"/> </path> <target name="compile"> <javac srcdir="src" includeantruntime="false" destdir="war/WEB-INF/classes" debug="on" fork="on" classpathref="master-classpath"/> </target> ... ...
  48. Example

  49. EXERCISE

  50. Eclipse + GlassFish • You can use Glassfish with some

    IDE • Netbeans, Eclipse, IntelliJ IDEA etc. • In Eclipse, install first GlassFish tools • Create dynamic web project and servlet • Choose "run on server"
  51. GlassFish Tools for Eclipse

  52. GlassFish Tools for Eclipse Search and Install GlassFish Tools

  53. Configure GlassFish Open Window > Preferences and add new Server

  54. Server Runtime Environment

  55. Hello World in Eclipse

  56. New Servlet

  57. Run on Server

  58. Troubleshooting • Mac OS X and Admin • If getting

    errors about policy files, please start the server from command line using admin – rights: • > sudo asadmin start-domain • If running into deploy problems ("can't deploy"), then "Use JAR archives for deployment" – option • Right click on glassfish from eclipse server tab. Then, select Properties > Glassfishand [x] Use JAR archives for deployment
  59. EXERCISE

  60. JAX-RS

  61. JAX-RS • JAX-RS is API that provides support for creating

    REST services • Uses annotations, introduces in Java SE 5 • Simplifies the process of implementing the services • JAX-RS 1.0 is a official part of Java EE 6 • JAX-RS 2.0 is a official part of Java EE 7 • In Glassfish no need to install anything • Can be downloaded separately (Jersey)
  62. JAX-RS Implementations • Implementations of JAX-RS include: • Jersey, the

    reference implementation from Oracle • http://jersey.java.net/ • RESTEasy, JBoss's implementation • http://www.jboss.org/resteasy • Apache CXF, an open source Web service framework • http://cxf.apache.org/docs/restful-services.html • Restlet, created by Jerome Louvel, a pioneer in REST frameworks • http://www.restlet.org/ • Apache Wink, Apache Software Foundation Incubator project, the server module implements JAX-RS • http://incubator.apache.org/wink/
  63. Java Annotation • Annotation is a metadata added to Java

    source code • Built-in annotations • @Override, @Deprecated .. • Possible to create custom annotations • @CustomAnnotation("someString") • Annotation are often used by frameworks by giving special behaviour to your code • Annotation are parsed using annotation processors • These can create for example additional Java code from the annotations
  64. JAX-RS Annotations • JAX – RS gives annotations where and

    plain old Java object (pojo) can be transformed to an resource that is accessed from URL • @Path • @GET, @PUT, @POST, @DELETE • @Produces • @Consumes
  65. Resource import javax.ws.rs.GET; import javax.ws.rs.Produces; import javax.ws.rs.Path; // The Java

    class will be hosted at the URI path "/helloworld" @Path("/helloworld") public class HelloWorldResource { // The Java method will process HTTP GET requests @GET // The Java method will produce content identified by the MIME Media // type "text/html" @Produces("text/html") public String doSomething() { String result = "<html><head><title></title></head><body><h1>Hello!</h1></body></html>"; return result; } }
  66. Resource Life Cycle • Resource instance is created for each

    new request • Life-cycle of root resource classes is per-request • Very natural programming model where constructors and fields can be utilized without concern for multiple concurrent requests to the same resource • Possible to change the life cycle to for example @Singleton • Only one instance per jax-rs application
  67. Deploying JAX-RS Service • You have couple choices to implement

    a starting point for your app 1. Extend Application to register root resources manually 2. Extend PackageResourceConfig to auto-scan paths
  68. 1) JAX-RS Application Model import java.util.HashSet; import java.util.Set; import javax.ws.rs.ApplicationPath;

    import javax.ws.rs.core.Application; // http://localhost:8080/TestApp/rest/helloworld @ApplicationPath("/rest") public class MyApplication extends Application { @Override public Set<Class<?>> getClasses() { final Set<Class<?>> classes = new HashSet<Class<?>>(); // @Path("/helloworld") classes.add(HelloWorldResource.class); return classes; } }
  69. 2) ResourceConfig package fi.tieturi.startingpoint; import javax.ws.rs.ApplicationPath; import org.glassfish.jersey.server.ResourceConfig; // http://localhost:8080/TestApp/rest/helloworld

    @ApplicationPath("/rest") public class MyApplication extends ResourceConfig { public MyApplication() { // Scanning packages for resources! packages("fi.tieturi.resources"); } }
  70. EXERCISE

  71. Query / Matrix Parameters

  72. @Path • @Path can be used to define path elements,

    at root level (class definition) or in method level • Class definition needs to have path, method definitions may have extra path to add • Paths are added to web app root context • http://server/webapp/resource/helloworld • Path may contain URI path templates, containing parameters • @Path("/users/{username}")
  73. Matrix vs Query params • Query params • http://some.where/thing?paramA=1&paramB=6542 •

    Matrix params • http://some.where/thing;paramA=1;paramB=6542
  74. Matrix Params • Matrix params • http://some.where/thing;paramA=1;paramB=6542 • Advantages •

    Can have more than one value: paramA=val1,val2 • No encoding and decoding & in XML • Can be anywhere in url, not just end • More readable? • Disadvantages • When submitting a FORM, query param is generated
  75. Example of Matrix and Query @Path("/class") public class MyResource {

    @Path("/matrix") @GET @Produces("text/plain") public String matrix(@MatrixParam("author") String author, @MatrixParam("title") String title) { String result = "matrix: author = " + author + " title = " + title; return result; } @Path("/query") @GET @Produces("text/plain") public String query(@QueryParam("author") String author, @QueryParam("title") String title) { String result = "query: author = " + author + " title = " + title; return result; } }
  76. @Produces • The @Produces annotation is used to specify the

    MIME media types of representations a resource can produce and send back to the client • Can be defined at class level as default, or method level to override • Legal values are any mime types your implementation supports, typical choices are text/html, text/xml, text/plain
  77. MIME Type • Two-part identifier for file formats transmitted on

    the internet • IANA official authority for th standardization • Composed of • type/subtype; optional parameters • Example • text/html; charset=UTF-8 • text/xml • text/plain • application/json • Top-level types: • application, audio, example, image, message, model, multipart, text, video
  78. JSON and XML • For JSON, use application/json • http://www.ietf.org/rfc/rfc4627.txt

    • For XML, use either text/xml or application/xml • http://www.rfc-editor.org/rfc/rfc3023.txt • "If an XML document -- that is, the unprocessed, source XML document -- is readable by casual users, text/xml is preferable to application/xml. " • "application/xml is preferable when the XML MIME entity is unreadable by casual users. "
  79. Example of Binary file public class MyResource { @Context ServletContext

    context; @GET @Path("/image") @Produces("image/png") public byte[] getImage() { try { File configFile = new File(context.getRealPath("image.png")); return Files.readAllBytes(configFile.toPath()); } catch(Exception e) { e.printStackTrace(); throw new WebApplicationException(404); } } ... JAX-RS provides @Context for injecting variety of resources in REST By using the ServletContext, we can get a real path to a image file New I/O api introduces in Java 7 Serve 404 if not found
  80. EXERCISE

  81. Developing REST Resource

  82. REST – recap (wikipedia)

  83. @Path("/users/{id}") class User { String user1 = "<user><id>1</id><name>Jack</name></user>"; String user2

    = "<user><id>2</id><name>Tina</name></user>"; String[] listOfUsers = {user1, user2}; @GET @Produces("text/xml") public String getUser(@PathParam("id") int id) { if(id >= 0 && id < listOfUsers.length) { return listOfUsers[id]; } else { return "<result>invalid ID</result>"; } } }
  84. @Path Example @Path("/users") class Users { // curl -X GET

    http://localhost:8080/Lab03/rest/users @GET @Produces("application/json") public String getUsers() { return "{result: 'HTTP GET all'}"; } // curl -X GET http://localhost:8080/Lab03/rest/users/1 @GET @Path("/{id}") @Produces("application/json") public String getUser(@PathParam("id") int id) { return "{result: 'HTTP GET with id ='" + id + "'}"; } // curl -X DELETE http://localhost:8080/Lab03/rest/users/1 @DELETE @Path("/{id}") @Produces("application/json") public String deleteUser(@PathParam("id") int id) { return "{result: 'HTTP DELETE with id ='" + id + "'}"; } }
  85. EXERCISE

  86. JSON PARSING

  87. @POST Example @Path("/users") class Users { // curl -X POST

    -d '{"id": 1, "firstname": "jack", "lastname": "pohjolainen"}' // http://localhost:8080/lab/users @POST public void addUser(String input) { ... } }
  88. JSR 353: Java API for JSON • JSON is a

    data exchange format widely used in web services and other connected applications • JSR 353 provides an API to parse, transform, and query JSON data • There are several libraries for JSON parsing, but JSR 353 is preinstalled in Java EE • Also JAXB for automatic conversion between POJO and JSON
  89. JSON • JSON defines only two data structures: objects and

    arrays • An object is a set of name-value pairs {} • An array is a list of values [] • JSON is often used as a common format to serialize and deserialize data in applications • RESTful web services use JSON extensively as the format for the data inside requests and responses • The HTTP header used to indicate that the content of a request or a response is JSON data is • Content-Type: application/json
  90. JSON Example {"employees":[ {"firstName":"John", "lastName":"Doe"}, {"firstName":"Anna", "lastName":"Smith"}, {"firstName":"Peter", "lastName":"Jones"} ]}

  91. JSR 353 Example String jsonText = "{\"key\": \"value\"}"; JsonReader reader

    = Json.createReader(new StringReader(jsonText)); JsonObject object = reader.readObject(); String name = object.getString("name");
  92. Main Classes Class or Interface Description Json Contains static methods

    to create JSON readers, writers, builders, and their factory objects. JsonGenerator Writes JSON data to a stream one value at a time. JsonReader Reads JSON data from a stream and creates an object model in memory. JsonObjectBuilder JsonArrayBuilder Create an object model or an array model in memory by adding values from application code. JsonWriter Writes an object model from memory to a stream. JsonValue JsonObject JsonArray JsonString JsonNumber Represent data types for values in JSON data.
  93. Creating Object Model @GET @Path("/json") @Produces(MediaType.APPLICATION_JSON) public String createJson() {

    JsonObjectBuilder builder = Json.createObjectBuilder(); builder.add("id", 1); builder.add("name", "jack"); JsonObject o = builder.build(); return o.toString(); }
  94. Streaming API • Object ModelAPI helps to convertJSON directly to

    genericobjects, and requiresreadingdocument at once • If documentsarelarge, or efficiency is the key, might be better to use StreamingAPI • Createa JsonParser, and parsea streamor String, • You can pull one event at time • Events are basically data structures, and you can do different handling based on data field name • When you need more events, you can say parser.next() • You can also write data using JsonGenerator
  95. @Consumes • @Consumes annotation is used to specify which MIME

    type can be accepted from the client • So if your service consumes JSON, you can use JsonObject as an method argument
  96. Example // curl -H "Content-Type: application/json" // -X POST -d

    '{"id": 1, "name": "jack"}' // http://localhost:8080/TestProject/rest/test/json @POST @Path("/json") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public JsonObject textProduces(JsonObject fromClient) { return fromClient; }
  97. Testing > curl -H "Content-Type: application/json" -X POST -d '{"id":

    1, "name": "jack"}' http://localhost:8080/TestProject/rest/test/json {"id":1,"name":"jack"} > curl -H "Content-Type: application/json" -X POST -d 'THIS IS NOT JSON' http://localhost:8080/TestProject/rest/test/json exception The Content-Type entity- header field indicates the media type of the entity- body sent to the recipient
  98. EXERCISE

  99. JAXB Converting POJO to JSON/XML and Back

  100. XML and Java • How do you read and write

    XML from Java? • Java API for XML Processing (JAXP) • Simple API for XML (SAX) • Event driven, only read • DOM Object Model (DOM) • Creates tree object in memory, read and manipulate • Java Architecture for XML Binding (JAXB) • Unmarshal xml file to Java objects • Marshal Java objects to xml file • JAXB available in Java SE 6 ->
  101. Web Server Server.java Book.java class Book { .. } class

    ClientApp { public static void main(String [] args) { Book book = new Book("Tuntematon Sotilas"); sendToServer(book); } } <book> <title> Java 8 new features </title> </book> Client Computer ClientApp.java Book.java This image cannot currently be displayed.
  102. JAXB Binding book.xsd book.xml book.java (class) new Book();

  103. JAXB • Java Architecture for XML Binding (JAXB) allows Java

    developers • marshal Java objects to XML • unmarshal XML back to Java objects • JAXB is part of Java SE • Implementation is done by using annotations • Package: javax.xml.bind.annotation.*; • @XmlRootElement, @XmlElement • Separate tools available • xjc -> schema to classes • schemagen -> classes to schema
  104. XML Schema (W3C) • Language for defining set of rules

    for XML – documents. • W3C Recommendation (2001) • More specific than DTD • Datatypes! • Is XML-language and it uses xml namespaces
  105. Schema Linking Defines the structure, tag names and order for

    all "book"- documents TAMK has created XML-language "Book" by defining it's rules in DTD.
  106. Simple Schema <?xml version="1.0"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="koululainen" type="koululaiset_tyyppi"/> <xsd:complexType

    name="koululaiset_tyyppi"> <xsd:sequence> <xsd:element name="etunimi" type="xsd:string"/> <xsd:element name="sukunimi" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:schema>
  107. Let's remove namespaces... <?xml version="1.0"?> <schema> <element name="koululainen" type="koululaiset_tyyppi"/> <complexType

    name="koululaiset_tyyppi"> <sequence> <element name="etunimi" type="string"/> <element name="sukunimi" type="string"/> </sequence> </complexType> </schema> It doesn't look so confusing after all?
  108. Marshal: Person.java import javax.xml.bind.annotation.*; @XmlType( propOrder = { "name", "age"}

    ) @XmlRootElement( name = "Person" ) public class Person { private String name; private int age; private int id; @XmlAttribute(name = "id", required = true) public void setId(int id) { this.id = id; } @XmlElement(name = "age") public void setAge(int age) { this.age = age; } @XmlElement(name = "name") public void setName(String name) { this.name = name; } ... }
  109. Marshal: Person.java import com.company.*; import javax.xml.bind.*; public class Main {

    public static void main(String[] args) throws Exception { Person person = new Person("Jack", 28, 123); JAXBContext jaxbContext = JAXBContext.newInstance( Person.class ); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); jaxbMarshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, true ); jaxbMarshaller.marshal(person, System.out); /* <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Person id="123"> <name>Jack</name> <age>28</age> </Person> */ } }
  110. List of Persons package com.company; import javax.xml.bind.annotation.*; import java.util.*; @XmlRootElement(

    name = "persons" ) public class Persons { List<Person> persons; @XmlElement( name = "person" ) public void setPersons(List<Person> persons) { this.persons = persons; } public List<Person> getPersons() { return this.persons; } }
  111. Marshalling a List import com.company.*; import javax.xml.bind.*; import java.util.*; public

    class Main { public static void main(String[] args) throws Exception { ArrayList<Person> personList = new ArrayList(); personList.add(new Person("jack", 28, 1)); personList.add(new Person("tina", 29, 2)); personList.add(new Person("john", 45, 3)); personList.add(new Person("samantha", 19, 4)); Persons persons = new Persons(); persons.setPersons(personList); JAXBContext jaxbContext = JAXBContext.newInstance(Persons.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); jaxbMarshaller.marshal(persons, System.out); } }
  112. Result and unmarshal <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <persons> <person id="1">

    <name>jack</name> <age>28</age> </person> <person id="2"> <name>tina</name> <age>29</age> </person> <person id="3"> <name>john</name> <age>45</age> </person> <person id="4"> <name>samantha</name> <age>19</age> </person> </persons>
  113. Unmarshal import com.company.*; import javax.xml.bind.*; import java.io.*; public class Main

    { public static void main(String[] args) throws Exception { File file = new File( "/path/to/persons.xml" ); JAXBContext jaxbContext = JAXBContext.newInstance( Persons.class ); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); Persons persons = (Persons) jaxbUnmarshaller.unmarshal( file ); System.out.println( persons.getPersons().get(0).getName() ); // jack } }
  114. Java Architecture for XML Binding (JAXB) • JAXB gives you

    the tools to • Transform Schema file (.xsd) to classes (.java) • xjc polygon.xsd • Transform classes (.java) to Schema (.xsd) • schemagen Class1.java ... ClassN.java
  115. Generate Schema From Classes > schemagen Persons.java Person.java > cat

    schema1.xsd <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="Person" type="person"/> <xs:element name="persons" type="persons"/> <xs:complexType name="persons"> <xs:sequence> <xs:element name="person" type="person" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="person"> <xs:sequence> <xs:element name="name" type="xs:string" minOccurs="0"/> <xs:element name="age" type="xs:int"/> </xs:sequence> <xs:attribute name="id" type="xs:int" use="required"/> </xs:complexType> </xs:schema>
  116. From Schema to Classes > xjc schema1.xsd parsing a schema...

    compiling a schema... generated/ObjectFactory.java generated/Person.java generated/Persons.java
  117. ObjectFactory • Sometimes Schema is not mappable to POJOs (Plain

    Old Java Objects) • In these cases JAXBElement wrapper objects are necessary to provide additional information • The xjc generated object model uses JAXBElement and therefore you need to way to construct these JAXBElement objects • ObjectFactory is for that • When using the ObjectFactory, unmarshaling is a bit complicated ...
  118. ... Unmarshal ObjectFactory import java.io.*; import javax.xml.bind.*; import generated.*; import

    java.util.*; public class Main { public static void main(String[] args) throws Exception { File file = new File( "/path/to/persons.xml" ); JAXBContext jaxbContext = JAXBContext.newInstance( ObjectFactory.class ); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); JAXBElement<Persons> jaxbElement = (JAXBElement<Persons>) jaxbUnmarshaller.unmarshal( file ); Persons persons = jaxbElement.getValue(); System.out.println( persons.getPerson().get(0).getName() ); // jack } }
  119. JAX-RS and JAXB • Glassfish is bundled with Jersey (https://jersey.java.net/)

    which is a reference implementation of JAX-RS • In JAX-RS the mapping between POJO and XML is done automatic!
  120. POJO @XmlRootElement class Planet { public int id; public String

    name; public double radius; }
  121. Resource @Path("planet") class Resource { @GET @Produces(MediaType.APPLICATION_XML) public Planet getPlanet()

    { final Planet planet = new Planet(); planet.id = 1; planet.name = "Earth"; planet.radius = 1.0; return planet; } }
  122. Result <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <planet> <id>1</id> <name>Earth</name> <radius>1.0</radius> </planet>

  123. MOXy • JSON binding is done by default a MOXy

    library • In Glassfish this is bundled! • In Desktop you can use • jaxbMarshaller.setProperty("eclipse.media- type", "application/json" ); • But usually you don't need to because of JAX-RS Client API that handles automatic conversion of JSON to POJO and back.
  124. Resource @Path("planet") class Resource { @GET @Produces(MediaType.APPLICATION_JSON) public Planet getPlanet()

    { final Planet planet = new Planet(); planet.id = 1; planet.name = "Earth"; planet.radius = 1.0; return planet; } }
  125. MOXy • EclipseLink MOXy component binds Java to JSON and

    back • http://www.eclipse.org/eclipselink/#moxy • JSON mapping differentiates datatypes • 1 => int, "hello" => String, true => boolean • JSON does not use attributes, @XmlAttribute is marshalled as an element • No Root element • See: • http://www.eclipse.org/eclipselink/documentati on/2.4/moxy/json003.htm
  126. EXERCISE

  127. BUILDING RESPONSES

  128. HTTP Request GET /u/874087/books.xml HTTP/1.1 Host: dl.dropboxusercontent.com:443 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/ *;q=0.8

    Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8,fi;q=0.6 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36 HTTP GET Request for a file books.xml
  129. HTTP Response HTTP/1.1 200 cache-control: max-age=0 content-disposition: inline; filename="build.xml"; filename*=UTF-

    8''build.xml content-encoding: gzip content-security-policy: referrer no-referrer content-type: application/xml date: Tue, 24 May 2016 07:10:09 GMT pragma: public server: nginx status: 200 x-content-security-policy: referrer no-referrer x-dropbox-request-id: 3179d488f019688a6649dda0711dc3fe x-robots-tag: noindex, nofollow, noimageindex x-server-response-time: 145 x-webkit-csp: referrer no-referrer HTTP Status 200 => OK 404 => Not Found ...
  130. HTTP Status Codes and REST Code Meaning 200 OK Response

    to a succesful GET, PUT or DELETE 201 Created Response to a POST that results a creation 205 No Content Succesful request that won't return a body like DELETE 404 Not Found Response when entity not found 400 Bad Request Response when request is incorrect 500 Internal Server Error Response when for example database connection fails
  131. WebApplicationException • It's possible to throw an Exceptions with the

    status code • throw new WebApplicationException(500); • Also predefined exceptions like • throw new InternalServerErrorException();
  132. Response Builder • Another way to set the status code

    is to use Response • Change your method to return Response – object • Response – object may also hold the content of the HTTP response
  133. Example of Response @Path("/test") public class TestResponse { @GET @Produces("text/plain")

    public Response testResponse() { Response.ResponseBuilder builder = Response.status(404); builder.entity("We failed to look for the entity."); Response response = builder.build(); return response; } }
  134. HTTP Response HTTP/1.1 404 Not Found Content-Length: 33 Content-Type: text/plain

    Date: Tue, 24 May 2016 07:36:51 GMT Server: GlassFish Server Open Source Edition 4.1 X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1 Java/Oracle Corporation/1.8) We failed to look for the entity.
  135. Example of POST @Path("/customers") public class TestResponse { @POST @Path("/{id}")

    @Produces(MediaType.APPLICATION_JSON) public Response testResponse(@PathParam("id") int id) { Response response; if(id >= 0) { // HTTP 201 Created Response.ResponseBuilder builder = Response.status(201); builder.entity("{'url': 'http://localhost:8080/TestProject/rest/test/" + id + "'}"); response = builder.build(); } else { // HTTP 400 Bad Request Response.ResponseBuilder builder = Response.status(400); response = builder.build(); } return response; } }
  136. Testing curl -X POST http://localhost:8080/TestProject/rest/test/1 {'url': 'http://localhost:8080/TestProject/rest/test/1'} curl -X POST

    http://localhost:8080/TestProject/rest/test/-1 ... HTTP Status 400 - Bad Request
  137. Shortcuts: HTTP 201 Created @GET @Path("/response") public Response response() {

    try { URI createdUri = new URI("http://.../rest/test/response/1"); return Response.created(createdUri).build(); } catch (URISyntaxException e) { e.printStackTrace(); throw new InternalServerErrorException("Invalid URI"); } }
  138. HTTP Response HTTP/1.1 201 Created Content-Length: 0 Date: Sun, 29

    May 2016 09:04:16 GMT Location: http://.../rest/test/response/1 Server: GlassFish Server Open Source Edition 4.1 X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1 Java/Oracle Corporation/1.8)
  139. HTTP Location • The HTTP Location header field is returned

    in responses from an HTTP server under two circumstances: • Ask a web browser to load different web page (URL Redirect). HTTP Status code should be 3xx redirection • Provide information about newly created resource. Http Status code should be 201
  140. Shortcuts: HTTP 200 OK and Body @GET @Path("/response") @Produces(MediaType.APPLICATION_JSON) public

    Response response() { // Build JSON Response JsonObjectBuilder builder = Json.createObjectBuilder(); builder.add("name", "jack"); JsonObject jsonObject = builder.build(); // Create response with HTTP Status 200 ResponseBuilder responseBuilder = Response.ok(jsonObject, MediaType.APPLICATION_JSON); // Build and return the response Response response = responseBuilder.build(); return response; }
  141. And even shorter ... @GET @Path("/response") @Produces(MediaType.APPLICATION_JSON) public Response response()

    { // Build JSON Response JsonObjectBuilder builder = Json.createObjectBuilder(); builder.add("name", "jack"); JsonObject jsonObject = builder.build(); return Response.ok(jsonObject, MediaType.APPLICATION_JSON).build(); }
  142. EXERCISE

  143. JDBC Connectivity

  144. JDBC Intro • Java Database Connectivity in Java since 1.1

    • Platform independent, Database independent • Wide range of data sources possible: • SQL, spreadsheets, flat files • JDBC API • Establish a connection to database • Execute SQL • Process the results
  145. Drivers • To access a database, you need a driver

    • To code in Java is always the same, changing the driver changes the connection to different database. • Lot’s of drivers for different databases: MySQL, Text, MS SQL Server..
  146. Driver Types https://ejbvn.wordpress.com/category/week-2-entity-beans-and-message-driven-beans/day-09-using-jdbc-to-connect-to-a-database/

  147. Driver Types • JDBC Drivers are divided into four categories

    • Type 1 that calls native code of the locally available ODBC driver. • Type 2 that calls database vendor native library on a client side. • Type 3, the pure-java driver that talks with the server-side middleware that then talks to database. • Type 4, the pure-java driver that uses database native protocol. • In most cases you can access the same database with four different type of drivers • List of drivers: • http://developers.sun.com/product/jdbc/drivers
  148. JDBC Classes http://docstore.mik.ua/orelly/linux/sql/ch14_01.htm

  149. Versions • JDBC was firstreleased in 1997 • Forward only,

    no updatable result sets • JDBC 2.0 • Scrollable an updatable result sets • JDBC 3.0 was included in J2SE 1.4 • More metadata, named parameters in callable statements, some new datatypes • JDBC 4.0, Java SE 6 • Easier driver loading, RowSet for offline use, XML-support • JDBC 4.1, Java SE 7 • JDBC 4.2, Java SE 8
  150. To use JDBC 1. Register driver 2. Access database 3.

    Do some SQL magic 4. Handle result 5. Close the connection
  151. public String jdbcConnection() { String result = ""; try {

    // 1. Register driver. Driver String is given to you by the driver // documentation. Driver (.jar) must be in classpath! Class.forName("com.mysql.jdbc.Driver"); // 2. Connect to database. Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test"); // 3. Some SQL Magic. Statement statement = conn.createStatement(); ResultSet rs = statement.executeQuery("SELECT * FROM Clients"); // 4. Handle Result while (rs.next()) { result += rs.getString("Firstname") + "<br>"; } // 5. Close the connection rs.close(); statement.close(); conn.close(); } catch (SQLException | ClassNotFoundException e) { e.printStackTrace(); } return result; }
  152. About ResultSet rs.next(); rs.next(); rs.next(); // Prints "Williams" System.out.println(rs.getString("Last Name"));

  153. public String jdbcConnection() { String result = ""; Connection conn

    = null; Statement statement = null; ResultSet rs = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://localhost/test"); statement = conn.createStatement(); rs = statement.executeQuery("SELECT * FROM Clients"); } catch (SQLException | ClassNotFoundException e) { e.printStackTrace(); } finally { try { if(rs != null) { rs.close(); } if(statement != null) { statement.close(); } if(conn != null) { conn.close(); } } catch(SQLException e) { e.printStackTrace(); } } return result; } The proper way of closing connection.
  154. public String jdbcConnection() { String result = ""; Connection conn

    = null; Statement statement = null; ResultSet rs = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://localhost/test"); statement = conn.createStatement(); rs = statement.executeQuery("SELECT * FROM Clients"); } catch (SQLException | ClassNotFoundException e) { e.printStackTrace(); } finally { try { // if(rs != null) { // rs.close(); // } if(statement != null) { statement.close(); } if(conn != null) { conn.close(); } } catch(SQLException e) { e.printStackTrace(); } } return result; } A ResultSet object is automatically closed when the Statement object that generated it is closed
  155. public String jdbcConnection() { String result = ""; try {

    Class.forName("com.mysql.jdbc.Driver"); // Java 7 autocloseable! try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test")) { // Java 7 autocloseable! try(Statement statement = conn.createStatement()) { ResultSet rs = statement.executeQuery("SELECT * FROM Clients"); while (rs.next()) { result += rs.getString("Firstname") + "<br>"; } } } } catch (SQLException | ClassNotFoundException e) { e.printStackTrace(); } return result; } Java 7 features autocloseable which closes the connection in right manner!
  156. public String jdbcConnection() { String result = ""; try {

    Class.forName("com.mysql.jdbc.Driver"); // Java 7 autocloseable! try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test")) { // Java 7 autocloseable! try(Statement statement = conn.createStatement()) { ResultSet rs = statement.executeQuery("SELECT * FROM Clients"); ResultSetMetaData rsmd = rs.getMetaData(); int numCols = rsmd.getColumnCount (); result = "<table>"; while (rs.next()) { result += "<tr>"; for (int i=1; i<=numCols; i++) { result += "<td>" + rs.getString(i) + "</td>"; } result += "</tr>"; } result += "</table>"; } } } catch (SQLException | ClassNotFoundException e) { e.printStackTrace(); } return result; } If you don't know the column names you can use ResultSetMetaData
  157. Eclipse + Glassfish + MySQL • Download MySQL Driver (.jar)

    • https://dev.mysql.com/downloads/connector/j/ • Drag the .jar to WebContent/WEB-INF/lib
  158. @Path("/helloworld") class HelloWorldResource { // The Java method will process

    HTTP GET requests @GET // The Java method will produce content identified by the MIME Media // type "text/html" @Produces("text/html") public String jdbcConnection() { String result = ""; try { Class.forName("com.mysql.jdbc.Driver"); try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test", "root", "root")) { try(Statement statement = conn.createStatement()) { ResultSet rs = statement.executeQuery("SELECT * FROM customers"); ResultSetMetaData rsmd = rs.getMetaData(); int numCols = rsmd.getColumnCount (); result = "<table>"; while (rs.next()) { result += "<tr>"; for (int i=1; i<=numCols; i++) { result += "<td>" + rs.getString(i) + "</td>"; } result += "</tr>"; } result += "</table>"; } } } catch (SQLException | ClassNotFoundException e) { e.printStackTrace(); result += e.toString(); } return result; } } Note, In real life you should use connection pool which is provided by you by the app server
  159. JAX-RS 2 IN MORE DETAIL

  160. JAX-RS 2 • JAX-RS 1.0 was unveiled in 2008 (JSR-311)

    • Java EE 7 included JAX-RS 2.0 (JSR-339) • Some New Features • Client API & Async • Server & Async • HATEOAS • Filters
  161. Client API and Async • JAX-RS 1.0 was strictly about

    server side • JAX-RS 2.0 introduces easy way to communicate with REST backend • This client API also async support with callback mechanism for waiting the result from server • Also async support for server
  162. Async on Server • In sync request/response mode • Pool

    of I/O threads • Server dedicates one thread from the pool • Process the request within the thread • Thread is released and put back to pool • Problem: huge number of requests and processing time-consuming -> all threads busy processing and pool is empty • Solution: Separate connection accepting and request processing to different threads
  163. Sync on Server @Path("/test") public class TestResponse { @GET @Path("/sync")

    @Produces(MediaType.TEXT_PLAIN) public String testSync() { System.out.println(Thread.currentThread().getName() + ": testSync: Start"); String result = expensiveOperation(); System.out.println(Thread.currentThread().getName() + ": testSync: End"); return result; } private String expensiveOperation() { try { int i=0; while(i < 5) { System.out.println(Thread.currentThread().getName() + ": expensive operation"); Thread.sleep(1000); i++; } } catch(Exception e) { e.printStackTrace(); } return "expensive operation ready"; } http-listener-1(5): testSync: Start http-listener-1(5): expensive operation http-listener-1(5): expensive operation http-listener-1(5): expensive operation http-listener-1(5): expensive operation http-listener-1(5): expensive operation http-listener-1(5): testSync: End
  164. Async on Server @Path("/test") public class TestResponse { @GET @Path("/async")

    @Produces(MediaType.TEXT_PLAIN) public void textAsync(@Suspended final AsyncResponse asyncResponse) { System.out.println(Thread.currentThread().getName() + ": textAsync: Start"); Thread thread = new Thread(() -> { String result = expensiveOperation(); asyncResponse.resume(result); }); thread.start(); System.out.println(Thread.currentThread().getName() + ": textAsync: End"); } http-listener-1(2): textAsync: Start http-listener-1(2): textAsync: End Thread-44: expensive operation Thread-44: expensive operation Thread-44: expensive operation Thread-44: expensive operation Thread-44: expensive operation
  165. HATEOAS • HATEOAS, Hypermedia as the Engine of Application State,

    is a constraint for REST • REST client enters app using fixed URL • All future actions can be discovered within resource representations • JAX-RS 2.0 provides Link classes for the links provided by the server
  166. Example (wikipedia) GET /account/12345 HTTP/1.1 Host: somebank.org Accept: application/xml

  167. Example (wikipedia) HTTP/1.1 200 OK Content-Type: application/xml <?xml version="1.0"?> <account>

    <account_number>12345</account_number> <balance currency="usd">100.00</balance> <link rel="deposit" href="http://somebank.org/account/12345/deposit" /> <link rel="withdraw" href="http://somebank.org/account/12345/withdraw" /> <link rel="transfer" href="http://somebank.org/account/12345/transfer" /> <link rel="close" href="http://somebank.org/account/12345/close" /> </account>
  168. Link Headers HTTP/1.1 200 OK Content-Type: application/xml Link: <http://somebank.org/account/12345/deposit>; rel=deposit

    Link: <http://somebank.org/account/12345/withdraw>; rel=withdraw ... <?xml version="1.0"?> <account> <account_number>12345</account_number> <balance currency="usd">100.00</balance> </account>
  169. Building Links Link link = Link.fromUri("http://{host}/root/customers/") .rel("update") .build(); Response response

    = Response.noContent() .links(link) .build();
  170. Filters • Server side • Request filters: before JAX-RS methods

    • Response filters: after JAX-RS methods • By default for all HTTP Requests • By using filter it's possible for example to modify incoming request in some way • Or do some authentication
  171. Pre Filter @Provider public class MyPreRequestFilter implements ContainerRequestFilter { public

    void filter(ContainerRequestContext ctx) throws IOException { long millisecs = System.currentTimeMillis(); ctx.setProperty("time", millisecs); } }
  172. Post Filter @Provider public class MyPostRequestFilter implements ContainerResponseFilter { public

    void filter(ContainerRequestContext req, ContainerResponseContext res) throws IOException { long before = ((Long) req.getProperty("time")).longValue(); long now = System.currentTimeMillis(); System.out.println("elapsed time: " + (now - before)/1000.0 + " s"); } }
  173. EXERCISE

  174. JAX-RS CLIENT API

  175. JAX-RS Client API • You can use HttpURLConnectionand implement the

    client "the hard way" • JAX-RS wraps the implementation of URLConnectionand provides easy way to communicate with RESTful backend • JAX-RS Client API is part of Java EE 7 • Client API reuses many aspects of JAX-RS
  176. Classes • Client – interface is the main entry point

    • ClientBuilder is used to create Client– objects • ClientBuilder.newClient() • Or use ClientBuilder.newBuilder() to give configuration properties • By using Client, you can create WebTarget that represents a specific URI • WebTarget target = client.target("http...."); • Invoke the request by using request() method which starts to build a request to client • Invocation.Builder b = client.request(); • Use get() – method to get the result
  177. Example // Download latest Jersey to client computer or reference

    to Glassfish jars. // https://jersey.java.net/download.html // Add api/, ext/ and lib/ from jersey to classpath // // From glassfish: lib/javaee.jar and modules/*.jar import javax.ws.rs.client.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; public class Main { public static void main(String[] args) { // Create client Client client = ClientBuilder.newClient(); // Target URL WebTarget webTarget = client.target("http://www.thomas-bayer.com/sqlrest/CUSTOMER/0"); // Create invocation Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_XML); // Get Response Response response = invocationBuilder.get(); // Read response to String String s = response.readEntity(String.class); // Print the response System.out.println(s); } }
  178. Result <?xml version="1.0"?><CUSTOMER xmlns:xlink="http://www.w3.org/1999/xlink"> <ID>0</ID> <FIRSTNAME>Laura</FIRSTNAME> <LASTNAME>Steel</LASTNAME> <STREET>429 Seventh Av.</STREET>

    <CITY>Dallas</CITY> </CUSTOMER>
  179. JAXB XML Binding public class Main { public static void

    main(String[] args) { // Create client Client client = ClientBuilder.newClient(); // Target URL WebTarget webTarget = client.target("http://www.thomas-bayer.com/sqlrest/CUSTOMER/0"); // Create invocation Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_XML); // Get Response Response response = invocationBuilder.get(); // Read response to String Customer c = response.readEntity(Customer.class); // Print the response: Laura System.out.println(c.getFirstname()); } } @XmlRootElement( name = "CUSTOMER" ) class Customer { public int getId() { return id; } @XmlElement(name = "ID") public void setId(int id) { this.id = id; } ...
  180. JAXB JSON Binding public class Main { public static void

    main(String[] args) { // Create client Client client = ClientBuilder.newClient(); // Target URL WebTarget webTarget = client.target("http://localhost:8080/customers/rest/customers/8"); // Create invocation Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON); // Get Response Response response = invocationBuilder.get(); Customer s = response.readEntity(Customer.class); // Print the response System.out.println(s.getFirstname()); } }
  181. JAXB JSON Binding public class Main { public static void

    main(String[] args) { // Create client Client client = ClientBuilder.newClient(); // Target URL WebTarget webTarget = client.target("http://localhost:8080/customers/rest/customers/8"); // Create invocation Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON); // Get Response Response response = invocationBuilder.get(); List<Customer> customers = response.readEntity(new GenericType<List<Customer>>() {}); ... } }
  182. import javax.ws.rs.client.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; public class Main {

    public static void main(String[] args) { // Create client Client client = ClientBuilder.newClient(); // Target URL WebTarget webTarget = client.target("http://localhost:8080/customers/rest/customers"); // Create invocation Invocation.Builder invocationBuilder = webTarget.request(); Customer customer = new Customer(112, "Keijo", "Virtanen"); Entity<Customer> e = Entity.entity(customer, MediaType.APPLICATION_JSON_TYPE); Response response = invocationBuilder.post(e); // Read response to String String s = response.readEntity(String.class); // Print the response System.out.println(s); } } Entity – class encapsulates Java object we want to send. It also has convienent methods like entity.json and entity.xml
  183. Using Response Response r = client.target("http://../customers/123") .request("application/json") .get(); try {

    if (r.getStatus() == 200) { Customer customer = r.readEntity(Customer.class); } } finally { response.close(); } To free up resources, it's good practice to close Response
  184. Async WebTarget webTarget = ClientBuilder.newClient().target("http://../rest/customers/"); Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON); AsyncInvoker

    ai = invocationBuilder.async(); ai.get(new InvocationCallback<String>() { @Override public void completed(String response) { System.out.println("Response " + response ); } @Override public void failed(Throwable throwable) { throwable.printStackTrace(); } });
  185. Swing + JAX-RS Client

  186. EXERCISE

  187. SECURITY

  188. Basic Stuff • Validation • Validate all inputs on the

    server, protect from SQL Injections • No sensitive data on URL • Send values in POST • Throw generic error Messages
  189. Encryption • REST has the same mechanisms as normal web

    browsing does: • VPN • SSL Encryption and HTTPs • Possible to do custom encryption using Authentication and Authorization API
  190. Securing • Authentication • Checking if user has given valid

    credentials, such as password • Web has standard protocols for authentication and Java EE support these • Authorization • Whether a certain user can access specific URI • You may allow PUT/POST/DELETE for others, and for others only GET • No web standard here, you need to configure your app server • Encryption • Use SSL, web defines https to leverage SSL and encryption • Usually these are not programming, it's all about configuration and applying annotations
  191. Authentication and Authorization • Limit the access of users •

    Basic authentication features • BASIC • Just username/password in request header • GET /..., authorization: Basic username:password • DIGEST • Username/password under encryption • password is never used directly by the protocol • CERTIFICATE • Usage of certificate given by trusted organization • Or you can implement your own way of identifying users, like token-based
  192. To turn on BASIC/DIGEST/CERTIFICATE • modify web.xml and set protected

    area • wildcards may be used • Set up user roles that can access URLs • Set up mode of authentication • See for example • http://java.boot.by/wcd-guide/ch05s03.html
  193. <web-app> <security-constraint> <web-resource-collection> <web-resource-name>Orders</web-resource-name> <url-pattern>/orders</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <role-name>admin</role-name>

    </auth-constraint> </security-constraint> <login-config> <auth-method>BASIC</auth-method> <realm-name>default</realm-name> </login-config> <security-role> <role-name>admin</role-name> </security-role> </web-app>
  194. Also in Code import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import

    javax.annotation.Security.RolesAllowed; @Path("/helloworld") @RolesAllowed({"ADMIN", "ORG1"}) public class helloWorld { @GET @Path("sayHello") @Produces("text/plain") @RolesAllows("ADMIN") public String sayHello() { return "Hello World!"; } }
  195. THANK YOU!