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

Building REST using Java

Building REST using Java

Jussi Pohjolainen

February 06, 2017
Tweet

More Decks by Jussi Pohjolainen

Other Decks in Technology

Transcript

  1. 2 Java as a Platform • Java is a set

    of software and specs developed by Sun and later acquired by Oracle • Java SE for Desktop • JRE does not come bundled with Windows or Mac OS X. In Linux, it depends on the distribution. • Java EE for Enterprise • Solid platform for developing backend services • Good compability with legacy systems • Web servers, application servers • Java ME for Mobile • Android uses Java language, but does not support Java ME! • Support today....? 2
  2. 3 Java Enterprise Edition • Java Enterprise Edition extends Java

    SE • Provides APIs and environment for "large-scale, multi-tiered, reliable and secure network applications". • Largely modular components running on application server • Uses heavily annotations • Also XML configurations can be used 3
  3. 4 Java EE Specifications • Java EE is defined by

    specifications • Some provider implements an API that meets this specification and can declare it's API as Java EE compliant • Several specifications • RMI, E-mail, Web services, EJBs, Servlets, JSPs .. • Java EE App Server handles securitys, scalability etc so developer can concentrate on business logic 4
  4. 6 Java EE EJB Web Application HTTP Request JDBC HTTP

    Response Web Server Servlet + JSP EJB Container EJBs RMI / SOAP / REST Direct Method / RMI / SOAP / REST 6
  5. 7 Java Application Servers • IBM Websphere • Oracle Weblogic

    • Apache Geronimo • Oracle Glassfish • ... 7
  6. 8 Tomcat vs Glassfish • Tomcat is a HTTP server

    and Java Servlet container • GlassFish is a full-blown Java EE app server, including the servlet container • Tomcat is more lightweight, easier to admin • GlassFish is a reference implementation of Java EE specification so it should contain all the latest features 8
  7. 9 Tools to use for Java EE • Lot of

    choice between IDEs. Also it's possible to work in CLI! • There is no "best" IDE • Some IDEs • Eclipse • Netbeans • IntelliJ IDEA • IBM Rational Developer • Oracle JDeveloper 9
  8. 11 What is Servlet? • It’s a specialized Java class,

    that handles HTTP Requests • extend HttpServlet • It will be instantiated it when needed, and removed from memory when it’s convenient • Server automatically runs servlet as threaded 11
  9. 12 Example: HelloWorld Servlet import java.io.*; import javax.servlet.*; import javax.servlet.annotation.*;

    import javax.servlet.http.*; @WebServlet("/HelloWorldServlet") public class HelloServlet extends HttpServlet { public void doGet( HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html><head><title>Hello World!</title></head>"); out.println("<body>"); out.println("<h1>Hello World!</h1>"); out.println("</body></html>"); } } 12
  10. 13 WAR package • Web applications contain • Compiled Java

    bytecode (Servlets, JavaBeans) in WEB-INF/classes folder • JSP pages • HTML pages • Images (gif, jpeg, png) • JavaScript and CSS stylesheeets • Configuration files in WEB-INF/ folder • Any extra libraries in WEB-INF/lib folder • All these are packaged together by your tool to a single package file with .war extension • .war files may be used as is or packaged into .ear file • Both .war and .ear can be then deployed in any compatible application server – to update just deploy a new .war on top of the old one 13
  11. 18 HTTP network protocol • HTTP is a network protocol

    of the Web • Hypertext Transfer Protocol • Delivers resources on the WWW • Usually delivered by TCP/IP • HTTP client sends a request to HTTP server • Default port is 80 • Resource can be a file or dynamically generated query result 18
  12. 19 Structure of HTTP • Consists of request and response

    • Format • an initial line, • zero or more header lines, • a blank line, • optional message body (this is the resource) • Example <initial line, different for request and response> Header1: value1 Header2: value2 <optional message body> 19
  13. 20 HTTP REQUEST: Initial Line • Initial line is different

    for the request than response. • Request line has three parts • method name, local path to resource, version of http • Example • GET /path/to/file/index.html HTTP/1.0 • Method name can be GET, POST, PUT, DELETE... 20
  14. 21 HTTP RESPONSE: Initial Line • The initial response line,

    called the status line • Typical status lines • HTTP/1.0 200 OK • HTTP/1.0 404 Not Found • Status code (200, 404) is computer-readable, reason phrase is human-readable • Status codes • 1xx, information message • 2xx, success • 3xx, redirect • 4xx, client error • 5xx, server error • See all status codes • http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 21
  15. 22 Header Lines • Header lines provide information about the

    request and response • Header-name: value • HTTP 1.0 provides 16 headers, HTTP 1.1 provides 46 headers • For example client should tell who is making the request • User-Agent: ... • Server should identify • Server: ... 22
  16. 23 Message Body • Message body contains the resource •

    Usually the message body includes header lines • Content-type: • MIME type of the resource, for example text/html, image/gif • Content-length • bytes 23
  17. 24 Example HTTP REQUEST and HTTP RESPONSE GET /MunSoftaniTestaus/MunHienoServlet HTTP/1.1

    Host: localhost:8080 User-Agent: curl/7.49.1 Accept: text/html HTTP/1.1 200 OK Server: GlassFish Server Open Source Edition 4.1.1 X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1.1 Java/Oracle Corporation/1.8) Content-Type: text/plain;charset=ISO-8859-1 Date: Tue, 10 Jan 2017 10:27:34 GMT Content-Length: 12 Hello World 24
  18. 25 Example HTTP REQUEST and HTTP RESPONSE POST /MunSoftaniTestaus/MunHienoServlet HTTP/1.1

    Host: localhost:8080 User-Agent: curl/7.49.1 Accept: */* Content-type: text/plain Content-Length: 9 Some data HTTP/1.1 200 OK Server: GlassFish Server Open Source Edition 4.1.1 X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1.1 Java/Oracle Corporation/1.8) Content-Type: text/plain;charset=ISO-8859-1 Date: Tue, 10 Jan 2017 10:39:58 GMT Content-Length: 10 Some data 25
  19. 26 Servlet Lifecycle • When request comes • Web container

    loads the servlet class • Creates an instance of the class • Calls init – method • Invokes service – method which invokes doGet, doPost ... • Only one instance of the object is created! • When several clients come, several threads are created • When container needs to remove the servlet, it calls destroy-method 26
  20. 28 Servlet methods • doGet • if the servlet supports

    HTTP GET requests • doPost • for HTTP POST requests • doPut • for HTTP PUT requests • doDelete • for HTTP DELETE requests • init and destroy • to manage resources that are held for the life of the servlet • getServletInfo, which the servlet uses to provide information about itself 28
  21. 29 Example: init and destroy @WebServlet("/HelloWorld2Servlet") public class HelloWorld2Servlet extends

    HttpServlet { public void init(ServletConfig config) throws ServletException { // Initialize any long-lasting resources here } protected void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Handle any web requests here } public void destroy() { // Release any long-lasting resources here } } 29
  22. 34 Request and Response public class HelloServlet extends HttpServlet {

    public void doGet( HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { ... } } 34
  23. 35 javax.servlet.http.HttpServletRequest • Request object is representation of HTTP request

    • To get Form and / or Url parameters • getParameter and getParameterValues • Http Headers can be accessed via getHeader/getHeaders methods • Some of these have own methods • getRemoteUser(), getRequestURI(), getContentLength(), getContentType(), getLocale(), getLocales(), etc • See the API reference for more details 35
  24. 36 HttpServletRequest examples protected void doGet(HttpServletRequest request, HttpServletResponse response) throws

    ServletException, IOException { // What browser? String useragent = request.getHeader("User-agent"); // GET/POST? String method = request.getMethod(); // Query String? String queryString = request.getQueryString(); // Parameter name? String parameterName = request.getParameter("name"); } 36
  25. 37 javax.servlet.http.HttpServletResponse • HttpServletResponse for the Http Response • You

    can write headers: • addHeader(String name, String value) • To write stuff to client: • getWriter() or getOutputStream() depending on if you want to print encoded text or raw bytes • Remember to set content type! • Also possibility to set error codes 37
  26. 38 HttpServletResponse examples // Set content type, and force a

    character set response.setContentType("text/html; charset=iso-8859-1"); // Create PrintWriter for printing text or OutputStream for bytes PrintWriter out = response.getWriter() ; OutputStream os = response.getOutputStream(); // Redirect browser to immediately load a new page response.sendRedirect("http://www.somecompany.com/") ; 38
  27. 39 Common Mime-Types Content-type Description text/html HTML content for HTML,

    XHTML, HTML 5 text/xml Generic XML content text/plain Plaintext application/pdf PDF Document application/json JSON format application/vnd.ms- excel MS Excel file image/gif, image/jpeg, image/png GIF/JPEG/PNG-format image 39
  28. 40 Common HTTP Headers http://en.wikipedia.org/wiki/List_of_HTTP_header_fields Field name Description Example Accept

    Content-Types that are acceptable Accept: text/plain Accept-Charset Character sets that are acceptable Accept-Charset: utf-8 Accept-Encoding Acceptable encodings. See HTTP compression. Accept-Encoding: <compress | gzip | deflate | sdch | identity> Accept-Language Acceptable languages for response Accept-Language: en-US Authorization Authentication credentials for HTTP authentication Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== Cache-Control Used to specify directives that MUST be obeyed by all caching mechanisms along the request/response chain Cache-Control: no-cache Connection What type of connection the user-agent would prefer Connection: close Cookie an HTTP cookie previously sent by the server with Set-Cookie (below) Cookie: $Version=1; Skin=new; Content-Length The length of the request body in octets (8-bit bytes) Content-Length: 348 Content-Type The mime type of the body of the request (used with POST and PUT requests) Content-Type: application/x-www-form-urlencoded Pragma Implementation-specific headers that may have various effects anywhere along the request-response chain. Pragma: no-cache Referer[sic] This is the address of the previous web page from which a link to the currently requested page was followed. (The word “referrer” is misspelled in the RFC as well as in most implementations.) Referer: http://en.wikipedia.org/wiki/Main_Page Refresh Used in redirection, or when a new resource has been created. This refresh redirects after 5 seconds. This is a proprietary, non-standard header extension introduced by Netscape and supported by most web browsers. Refresh: 5; url=http://www.w3.org/pub/WWW/People.html User-Agent The user agent string of the user agent User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) Via Informs the server of proxies through which the request was sent. Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) Warning A general warning about possible problems with the entity body. Warning: 199 Miscellaneous warning 40
  29. 43 Cookies • An HTTP cookie is a small piece

    of data sent from a website and stored on the user's computer • can be used to remember the state of web application, such as shopping cart in an online store. • Session cookie • Destroyed when browser is closed • Persistent cookie • Specific date when expires • Cookies are stored in browser • Structure is really simple: name, value and attributes (expiration date) 43
  30. 44 HTTP Request and Response GET /myservlet HTTP/1.0 Host: localhost:8080

    HTTP/1.0 200 OK Content-type: text/html Set-Cookie: name=value; Expires=Wed, 09 Jun 2021 10:20:15 GMT 44
  31. 46 Servlet and Cookie • Creating a cookie Cookie c

    = new Cookie(name, value); response.addCookie(c); • Reading a cookie Cookie[] allCookies = request.getCookies(); 46
  32. 49 Example HTTP REQUEST and HTTP RESPONSE POST /MunSoftaniTestaus/MunHienoServlet HTTP/1.1

    Host: localhost:8080 User-Agent: curl/7.49.1 Accept: */* Content-type: text/plain Content-Length: 9 Some data HTTP/1.1 200 OK Server: GlassFish Server Open Source Edition 4.1.1 X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1.1 Java/Oracle Corporation/1.8) Content-Type: text/plain;charset=ISO-8859-1 Date: Tue, 10 Jan 2017 10:39:58 GMT Content-Length: 10 Some data 49
  33. 50 Example HTTP REQUEST and HTTP RESPONSE POST /MunSoftaniTestaus/MunHienoServlet HTTP/1.1

    Host: localhost:8080 User-Agent: curl/7.49.1 Accept: */* Content-type: application/x-www-form-urlencoded Content-Length: ... name=vili&password=secret HTTP/1.1 200 OK Server: GlassFish Server Open Source Edition 4.1.1 X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1.1 Java/Oracle Corporation/1.8) Content-Type: text/plain;charset=ISO-8859-1 Date: Tue, 10 Jan 2017 10:39:58 GMT Content-Length: 10 Login successful 50
  34. 51 Example Form <form method="post" action="GetAndPostServlet"> <fieldset> <legend>Feedback Form</legend> <input

    type="text" name="name" placeholder="Name" size="40"/> <input type="text" name="email" placeholder="Email" size="40"/> <button type="submit" class="pure-button pure-button-primary">Send</button> </fieldset> </form> Use either get or post The url where servlet is 51
  35. 52 Receiving Parameters @WebServlet("/GetAndPostServlet") public class GetAndPostServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); String email = request.getParameter("email"); String output = "Name = " + name + "<br>E-mail = " + email; response.setContentType("text/html"); } } 52
  36. 53 Example Form <form method="get" action="GetAndPostServlet"> <fieldset> <legend>Feedback Form</legend> <input

    type="text" name="name" placeholder="Name" size="40"/> <input type="text" name="email" placeholder="Email" size="40"/> <button type="submit" class="pure-button pure-button-primary">Send</button> </fieldset> </form> Change to GET 53
  37. 55 Receiving Parameters @WebServlet("/GetAndPostServlet") public class GetAndPostServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); String email = request.getParameter("email"); String output = "Name = " + name + "<br>E-mail = " + email; response.setContentType("text/html"); } } 55
  38. 56 Form and Select <form method="get" action="GetAndPostServlet"> <fieldset> <legend>Form</legend> <input

    type="text" name="name" placeholder="Name" size="40"/> <input type="text" name="email" placeholder="Email" size="40"/> Your car: <select name="cars" multiple="true"> <option value="volvo">Volvo</option> <option value="saab">Saab</option> <option value="mercedes">Mercedes</option> <option value="audi">Audi</option> </select> <button type="submit" class="pure-button pure-button-primary">Send</button> </fieldset> </form> 56
  39. 57 Get Multiple Values public class GetAndPostServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ... List<String> cars = Arrays.asList(request.getParameterValues("cars")); String output = "Name = " + name + "<br>E-mail = " + email; for(String car : cars) { output += "<br>car = " + car; } } getParameterValues will return a String array 57
  40. 60 Validation • Web app can be divided into three

    layers 1. Presentation (HTML) 2. Business Logic (Servlet, Java-classes) 3. Database • Layer 1 may validate user input • For example HTML5 Forms, JavaScript etc • Layer 2 always has to do validation • Before entering anything to database, check that user has given valid format. For example "school grade" could be a number between 4 – 10. • Layer 3 should do simple validation • By declaring column types to tables, you create very simple validation to the database 60
  41. 61 Layer 1: Validation <form action="saveUserFeedBackServlet"> <input type="text" name =

    "userfeedback" placeholder = "Is this a good course?" pattern = "Yes|Excellent|Magnificent" title = "Feedback must be Yes, Excellent or Magnificent"><br> <input type="submit" value="Save Feedback"> </form> 61
  42. 62 Layer 2: Validation • Check for not null! •

    Filter dangerous characters away, for example < and > might be dangerous because of html • If user gives <, replace it with &lt;. And > for &gt; • Watch out for SQL Injection • Use Regex for more advanced validation 62
  43. 63 Filter away HTML/XML public static String filterHtml(String input) {

    input = input.replace("<", "&lt;"); input = input.replace(">", "&gt;"); ... return input; } 63
  44. 64 SQL Injection • If user input is part of

    SQL – statement, you may run into trouble • String sql = "SELECT * FROM Customers WHERE UserId = " + userInput; • If user gives input • "1; DROP TABLE Customers" • Then we will have following SQL: • SELECT * FROM Customers WHERE UserId = 1; DROP TABLE Customers • Solution • Filter unwanted characters – may be not a very good idea • Use SQL parameters (JDBC: Prepared statements) 64
  45. 65 Regular Expressions • Designed to help working with strings

    in UNIX environment • Easy way to find a pattern in a string and/or replace it if you want • Very powerful tool • There are several different versions of Regex • Java Regex is very similar to regex found in Perl 65
  46. 66 Basic Syntax • In Regex, one uses patterns •

    Pattern can hold • Normal characters • Start and end indicators as ^ and $ • Count indicators like +, - , ? • Logical operators, like | • Grouping with {}, (), [] • Example (Perl-compatible) • /^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,5}$/ 66
  47. 67 Perl Regex Examples • Basic usage: /pattern/modifiers • Examples:

    • /ha jo/ matches "turha jono" • /ha jo/i matches "turha JONO"; 67
  48. 68 Some PERL regex rules REGEX Explanation Example . Any

    single character /a.c/ matches "abc" or "afc" [ ] Single character that is contained within the brackets /[abc]/ matches "a", or "b" or "c" ^ Find from the beginning of the string /^a/ matches "aku ankka" $ Find from the end of the string /a$/ matches "aku ankka" | OR /cat|dog/ matches "dog" or "cat" ^ NOT (when used in middle of pattern) /a^aa/ matches "aba" {n,m} Matches min n, max m /a{1,3}/ matches "a", or "aa", or "aaa" * Matches 0-n /a*/ ? Matches 0-1 /(hello)?/ + Matches 1-n /a+/ 68
  49. 69 Examples • /.ala/ • kavalampi • /\. Älä/ •

    Nyt se loppui. Älä rupea. • /^begin/ • begin starts like this. • /end$/ • this is the end 69
  50. 70 Examples • /^begin and end$/ • begin and end

    • /one|two|three/ • this is the one • /[abc]$/ • dkdkdka 70
  51. 71 More Perl REGEX Rules REGEX Explanation \w [a-zA-Z0-9_] \W

    ^[a-zA-Z0-9_] \n New Line \s Whitespace / Empty \S Not whitespaces / Empty \d Number \D Not Number 71
  52. 73 Java Regex Example: We Found it! import java.util.regex.Matcher; import

    java.util.regex.Pattern; public class RegexExample { public static void main(String[] args) { // REGEX Pattern pattern = Pattern.compile("jack"); Matcher matcher = pattern.matcher("xxx jack xxx"); if(matcher.find()) { System.out.println("We found it!"); } else { System.out.println("nope"); } } } 73
  53. 74 Java Regex Example: Nope import java.util.regex.Matcher; import java.util.regex.Pattern; public

    class RegexExample { public static void main(String[] args) { // REGEX Pattern pattern = Pattern.compile("^jack$"); Matcher matcher = pattern.matcher("jackjack"); if(matcher.find()) { System.out.println("We found it!"); } else { System.out.println("nope"); } } } 74
  54. 75 Java Regex Example: We Found it! import java.util.regex.Matcher; import

    java.util.regex.Pattern; public class RegexExample { public static void main(String[] args) { // REGEX Pattern pattern = Pattern.compile("^jack$"); Matcher matcher = pattern.matcher("jack"); if(matcher.find()) { System.out.println("We found it!"); } else { System.out.println("nope"); } } } 75
  55. 76 Java Regex Example: We Found it! import java.util.regex.Matcher; import

    java.util.regex.Pattern; public class RegexExample { public static void main(String[] args) { // REGEX \\. = . Pattern pattern = Pattern.compile("^[+-]?\\d+\\.?\\d*$"); Matcher matcher = pattern.matcher("+33.33"); if(matcher.find()) { System.out.println("We found it!"); } else { System.out.println("nope"); } } } 76
  56. 77 Java Regex Example: We Found it! import java.util.regex.Matcher; import

    java.util.regex.Pattern; public class RegexExample { public static void main(String[] args) { // REGEX Pattern pattern = Pattern.compile("(?i)tomaatti"); Matcher matcher = pattern.matcher("xxx TomAatti xxx"); if(matcher.find()) { System.out.println("We found it!"); } else { System.out.println("nope"); } } } 77
  57. 78 Java Regex Example: nope import java.util.regex.Matcher; import java.util.regex.Pattern; public

    class RegexExample { public static void main(String[] args) { // When using matches, it's ^tomaatti$ by default Pattern pattern = Pattern.compile("tomaatti"); Matcher matcher = pattern.matcher("xxx tomaatti xxx"); if(matcher.matches()) { System.out.println("We found it!"); } else { System.out.println("nope"); } } } 78
  58. 79 Java Regex Example: We found it! import java.util.regex.Matcher; import

    java.util.regex.Pattern; public class RegexExample { public static void main(String[] args) { // When using matches, it's ^tomaatti$ by default Pattern pattern = Pattern.compile("[a-z]"); Matcher matcher = pattern.matcher("a"); if(matcher.matches()) { System.out.println("We found it!"); } else { System.out.println("nope"); } } } 79
  59. 80 Java Regex Example: We found it! import java.util.regex.Matcher; import

    java.util.regex.Pattern; public class RegexExample { public static void main(String[] args) { // When using matches, it's ^tomaatti$ by default Pattern pattern = Pattern.compile("tomaatti.*"); Matcher matcher = pattern.matcher("tomaattihellurei"); if(matcher.matches()) { System.out.println("We found it!"); } else { System.out.println("nope"); } } } 80
  60. 81 String.matches • Matcher creates precompiled regex and it's possible

    to reuse it • String has also matches(String regex) method but it will create the regex each time • Example public class RegexExample { public static void main(String[] args) { if("tomaattihellurei".matches("tomaatti.*")) { System.out.println("We found it!"); } else { System.out.println("nope"); } } } 81
  61. 82 Servlet and Regex public static final Pattern PATTERN =

    Pattern.compile("Yes|Excellent|Magnificent"); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain"); try (PrintWriter out = response.getWriter()) { String feedback = request.getParameter("userfeedback"); if(feedback != null) { Matcher matcher = PATTERN.matcher(feedback); if(matcher.matches()) { out.println("save to database"); } else { out.println("incorrect value."); } } } } 82
  62. 85 JDBC Intro • Java Database Connectivity in Java since

    1.1 • Platform independent, Database independen • Wide range of data sources possible: • SQL, spreadsheets, flat files • JDBC API • Estabish a connection to database • Execute SQL • Process the results 85
  63. 86 To use JDBC 1. Register driver 2. Access database

    3. Do some SQL magic 4. Handle result 5. Close the connection 86
  64. 87 public static 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; } 87
  65. 89 executeUpdate String sql = "INSERT INTO ..."; Statement statement

    = conn.createStatement(); int numberOfRowsUpdated = statement.executeUpdate(sql); if(numberOfRowsUpdated > 0) { System.out.println("Updated successful!"); } 89
  66. 90 public static 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. 90
  67. 91 public static 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 91
  68. 92 public static 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! 92
  69. 93 public static String jdbcConnection() { String result = "";

    try { Class.forName("com.mysql.jdbc.Driver"); // Java 7 autocloseable! try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test"); { 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; } You can hook these into inside of one try(..). 93
  70. 94 // 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(); } If you don't know the column names you can use ResultSetMetaData 94
  71. 95 Transactions • If you want to commit several sql

    – commands into one: • conn.setAutoCommit(false); • // do some sql • conn.commit(); • conn.rollback(); 95
  72. 96 Prepared Statements • Prepared statement or parameterized statement is

    a feature used to execute the same or similar database statements repeatedly with high efficiency • Simple way to protect against SQL injection String sql = "UPDATE table1 set one = ?, two = ?"; PreparedStatement preStmt = con.prepareStatement(sql); preStmt.setInt(1, 123); preStmt.setString(2, "myNewValue2"); preStmt.executeUpdate();
  73. 98 Creating and closing connections • In Servlet Context (Web

    App), opening when loading, closing when destroying • Problem: one connection is reserved for the whole lifespan of the app, what if you have multiple web apps doing the same thing? • In Servlet init and destroy – methods • Problem: one connection is reserved for the whole lifespan of the servlet, what if you have multiple servlets doing the same thing? • In doGet or doPost • Problem: creating and destroying the connection is expensive • Solution: Connection Pooling 98
  74. 99 Configuring Connection Pool • Connection Pool is provided by

    you by the app server (Glassfish) • You will have to create new connection pool and set a JNDI name for it • Java Naming and Directory (JNDI) service allow to look up services • Connection Pool is a service • App connects to JNDI and JDNI connects to the connection pool • It's possible to configure the connection pool and the app does not know about it! • To configure the 1) connection pool and 2) jndi – name, use glassfish admin web page or cli • Note: in Glassfish 4.1.1 the web admin is broken, use 4.1.0 or Payara 99
  75. 100 To Create new Connection Pool • PoolName: CanBeWhatEver •

    Resource Type: • DataSource (App Server Connection Pool) • ConnectionPoolDataSource (JDBC Driver pooling) • XADatasource (Distributed transaction for multiple databases) • SqlDriver (basic jdbc) 100
  76. 104 public class ConnectionPool extends HttpServlet { private DataSource ds;

    public void init(ServletConfig config) throws ServletException { try { // JNDI Lookup can be slow, let's do it only one time. // You will have to specify the JNDI name in Glassfish admin! Context ctx = new InitialContext(); ds = (DataSource) ctx.lookup("MyDatabaseJNDI"); } catch (NamingException e) { e.printStackTrace(); } } protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); try (PrintWriter out = response.getWriter()) { out.println(derbyConnection()); } } private String derbyConnection() { String result = "<pre>"; String sql = "SELECT * FROM DUCKBURG_RESIDENTS"; // Let's ask the connection from the datasource! try (Connection c = ds.getConnection()) { try (Statement statement = c.createStatement()) { ResultSet rs = statement.executeQuery(sql); while (rs.next()) { result += rs.getString("id") + " " + rs.getString("firstname") + " " + rs.getString("lastname") + "\n"; } } } catch (Exception e) { e.printStackTrace(System.out); } return result + "</pre>"; } 104
  77. 107 JPA • Java Persistence API (JPA) is an specification

    that describes management of relational data in apps using Java • The reference implementation for JPA is EclipseLink • http://www.eclipse.org/eclipselink/#jpa • Basic idea is simple, save objects to relational database 107
  78. 108 Quick Steps 1. Create persistence.xml file to meta-inf/ dir

    under your classes/ dir • This file declares for example what database (derby, mysql, ...) you are accessing 2. Annotate your POJO – class so that it JPA knows which table is used for storing the objects from this class 3. Implement the saving / retrieving using javax.persistence classes 108
  79. 109 <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">

    <persistence-unit name="basicjpapu" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver" /> <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/test-jpa6;create=true" /> <!-- create tables if needed --> <property name="javax.persistence.schema- generation.database.action" value="create"/> <property name="javax.persistence.jdbc.user" value="APP" /> <property name="javax.persistence.jdbc.password" value="APP" /> </properties> </persistence-unit> </persistence> 109
  80. 110 Annotations @Entity @Table(name="DUCKBURG_RESIDENTS") public class Person { @Id @GeneratedValue(strategy

    = GenerationType.IDENTITY) private int id; private String firstname; private String lastname; public Person() {} public int getId() { return id; } 110
  81. 111 Code EntityManagerFactory factory = Persistence.createEntityManagerFactory("basicjpapu"); EntityManager em = factory.createEntityManager();

    em.getTransaction().begin(); Person p = new Person(); p.setFirstname("Mickey"); p.setLastname("Mouse"); // p.setId(7); em.persist(p); em.getTransaction().commit(); em.close(); 111
  82. 112 Entity • Annotate class with the @Entity • JPA

    will create a table for the entity • By default table name is class name • You can change this by using @Table annotation • Instances of the class will be a row in the table • All entity classes must define a primary key • You can auto-generate the primary key in the database using @GeneratedValue annotation 112
  83. 113 Annotations @Entity @Table(name = "employees") public class Employee {

    // Each pojo will have a primary // key which you annotate // by using @Id @Id @Column(name = "id") private int id; @Column(name = "firstname") private String firstName; @Column(name = "lastname") private String lastName; 113
  84. 114 Annotations @Entity @Table(name = "employees") public class Employee {

    // Each pojo will have a primary key which // you annotate // by using @Id @Id // Define strategy how to save this to db // IDENTIFY allow auto increment on demand in Derby/MySQL @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name = "id") private int id; @Column(name = "firstname") private String firstName; @Column(name = "lastname") private String lastName; 114
  85. 115 Java Persistence Query Language • JPQL is a language

    defined in JPA specification • Based on SQL syntax • You work with classes and objects instead of records and fields • Template • SELECT ... FROM ... WHERE ... ORDER BY ... • Minimal JPQL Query • Select object FROM Employee as object • The FROM clause specifies query variable (like loop variable in programming) 115
  86. 116 In Code Query query = em.createQuery("Select obj from Employee

    as obj"); List<Employee> list = query.getResultList(); 116
  87. 119 persistence.xml <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence

    http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="persons" transaction-type="JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>MyDatabaseJNDI</jta-data-source> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="javax.persistence.schema-generation.database.action" value="create"/> </properties> </persistence-unit> </persistence> 119
  88. 120 Code @PersistenceContext(unitName = "persons") private EntityManager em; @Resource private

    UserTransaction userTransaction; public void doIt() { //EntityManagerFactory factory = Persistence.createEntityManagerFactory("persons"); //EntityManager em = factory.createEntityManager(); //em.getTransaction().begin(); try { userTransaction.begin(); Person p = new Person(); p.setFirstname("Jack"); p.setLastname("Smith"); em.persist(p); userTransaction.commit(); } catch(Exception e) { e.printStackTrace(); } } 120
  89. 121 EntityManager is not Thread Safe • In the previous

    code, EntityManager was declared as an attribute • When several threads are accessing the EntityManager at the same time, thing can go wrong • Usually the architecture is following • jsp (view) -> servlet (controller) -> EJB/JPA (Model) -> DB • When using the JPA in EJB, attributes are thread safe and you don't have to worry about it. Also transactions are handled for you. • In servlet, you will have to look up the EntityManager 121
  90. 122 @PersistenceContext(unitName="test-pu", name="persistence/em/test") public class TLInjectionServlet extends HttpServlet { @Resource

    private UserTransaction userTrx; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { EntityManager em = null; try { Context ic = new InitialContext(); em = (EntityManager) ic.lookup("java:comp/env/persistence/em/test"); } catch (NamingException e) { throw new ServletException(e); } try { userTrx.begin(); Employee employee = new Employee(...); em.persist(employee); userTrx.commit(); } catch (Exception e) { throw new ServletException(e); } } } 122
  91. 124 Using EJB @Stateless public class DatabaseHandlerEJB implements JPAManager {

    @PersistenceContext(unitName = "employeedb") private EntityManager em; @Override public List<Object> getEmployees() throws Exception { Query query = em.createQuery("Select obj from Employee as obj"); return query.getResultList(); } } 124
  92. 127 Rest • Representational State Transfer was introduced and defined

    in 2000 by Roy Fielding in his theses: • http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_s tyle.htm • Way of providing interoperability between computer systems • Does not restrict communication to a particular protocol • Http Web Service API that follows REST principals are called RESTful APIs
  93. 128 What makes Rest a Rest? 1. Client – Server

    2. Stateless 3. Cacheable 4. Layered system 5. Code on demand (optional) 6. Uniform Interface 1. Identification of resources 2. Manipulation of resources through representations 3. Self-descriptive messages 4. Hypermedia as the engine of application state
  94. 129 1. Client Server • Separate UI from the data

    improves portability of the UI • Improve scalability by simplifying server components • Both components, client and server, can evolve independently
  95. 130 2. Stateless • Client - server communication must be

    stateless in nature • No session data stored on the server • Each request from client to server must contain all the information necessary to understand the request
  96. 131 3. Cache • Responses should define themselves as cacheable

    or not • Eliminate client-server interactions • In Restful, you can do this by using HTTP Headers
  97. 132 Client Server Cache Client Cache Request contains all information

    Client may store the response to a cache and reuse it
  98. 133 4. Layered System • Rest can be built using

    multiple architecture layers • Restrict knowledge of the system to one layer • Client -> Cache -> middleware -> server -> db • For example the middleware can be a cache • Client cannot tell if it's connected to end server or middleware
  99. 134 5. Code on Demand (optional) • Client can download

    JavaScript, Flash or Java Applet from server • Server can decide how things are done
  100. 135 6. Uniform Interface • Uniform Interface has four constraints

    1. Identication of resources • Every resource has unique URI 2. Manipulation of resources through representations • Representation can be in various formats and is de-coupled from the identification 3. Self-descriptive messages • Each message has enough information to describe how to process the message, for example by using content-type 4. Hypermedia as the engine of application state (HATEOAS) • Server respondes with a set of links what other actions are available
  101. 136 6.1 Identification of Resources • Every resource has it's

    own unique URI • http://company.com/employees/ • URI is an identifier • Result is the resource • Notice that resource is not 'storage object', it's entity • Resources are just some item that can be accessed
  102. 137 6.2 Representation • Identified resource can be returned in

    various formats, like HTML, XML, JSON, SVG, PNG • RESTful apps can send accept header where it defines what kind of data it can handle • Server can send Content-type where it defines the type of the resource • De-coupling the representation of the resource from the URI is key aspect of REST
  103. 138 6.3 Self-descriptive Messages • Each client and server response

    is a message • Message should be self-descriptive • Message contains the body and metadata • In Restful, you use HTTP GET, PUT and HTTP Headers for this
  104. 139 6.4 HATEOAS • In perfect you don't need documentation

    for the API • Include links to the responses • What other • REST client needs no prior information about the service • REST client enters app by simplex fixed URI • All future actions may be discovered within the response • Nearly ALL popular WEB APIs violate HATEOAS
  105. 140 HATEOAS (wikipedia) HTTP/1.1 200 OK Content-Type: application/xml Content-Length: ...

    <?xml version="1.0"?> <account> <account_number>12345</account_number> <balance currency="usd">100.00</balance> <link rel="deposit" href="https://somebank.org/account/12345/deposit" /> <link rel="withdraw" href="https://somebank.org/account/12345/withdraw" /> <link rel="transfer" href="https://somebank.org/account/12345/transfer" /> <link rel="close" href="https://somebank.org/account/12345/close" /> </account>
  106. 144 Rest and Web Services • Web Service API that

    follows REST principals are called RESTful APIs • HTTP based RESTful APIs are defined with following aspects • base url • standard http methods
  107. 149 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
  108. 150 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
  109. 156 URLs and Actions • Identify resources • Use nouns,

    like ticket, user or group • Identify what actions can user apply to them • GET /employees/ • GET /employees/1 • POST /employees • PUT /employees/1 • DELETE /employees/1 • Use plurals in the endpoint name! • So do not: employee/1 vs employees/ • person / people vs goose / geese
  110. 157 Relations • Group logically relations • GET /threads/1/messages •

    GET /threads/1/messages/1 • POST /threads/1/messages
  111. 158 Update and Delete • When creating, updating return the

    updated resource to the client • In case of HTTP POST, return 201 and include Location Header that points to the URL of the resource • In case of HTTP DELETE • 204: no response body • 200: response body with the deleted resource
  112. 159 Status Codes • 200 OK (HTTP GET) • 201

    Created (HTTP POST) • 204 No Content (For example Delete) • 400 Bad Request • 401 Unauthorized • 403 Forbidden • 404 Not Found • 405 Method not found (when method is not allowed for authenticated user) • 409 Conflict • 410 Gone (older apis) • 429 Too many requests
  113. 160 Errors • Return sensible HTTP status codes • 400

    -> client issues • 500 -> server issues • Also send JSON explaining the error • { "code" : 1234, "message" : "Something bad happened :(", "description" : "More details about the error here" }
  114. 162 Pretty Print or Not? • If you don't have

    indentation and whitespaces it's hard to detect the structure of the response • Extra cost is data transfer, but it is really small cost if you use gzip
  115. 163 Caching • HTTP Provides built-in caching framework • Can

    be done both in client or in server-side
  116. 165 Filtering, sorting & searching • Use query parameters •

    Filtering • GET /employees?firstname=jack • Sorting • GET /employees?sort=firstname • Searching • GET /employees?q=jack • Combining • GET /employees?q=jack&sort=salary
  117. 166 Limiting • If full representation is not needed •

    GET employees?fields=firstname,lastname
  118. 168 Authentication • Rest API should be stateless • Authentication

    should not depend on cookies or sessions • Each request should have some sort of authentication • By using SSL, you can send access token via HTTP Basic auth
  119. 169 Non-CRUD • What about operations that are not Create,

    Read, Update or Delete? • Can be fuzzy • PUT /employees/1/dosomething • POST /search
  120. 170 Documentation • API is only good as it's documentation

    • Well if you have really good API you don't need documentation (HATEOAS) • See GitHub • https://developer.github.com/v3/gists/#list-gists • See TAMK Open Data • http://avoindata.tamk.fi/en/
  121. 171 Consider Versioning • It's possible to version your API

    • Can be included in URL or in Header • Stripe uses version in URL and in header • curl https://api.stripe.com/v1/charges \ -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \ -H "Stripe-Version: 2017- 01-27" • https://stripe.com/docs/upgrades#api-changelog
  122. 172 JSON or XML • If creating Web Service, JSON

    is the way to go • If large number of enterprise customers, maybe XML is better • Lot of public Web APIs are dropping support to xml?
  123. 173 Rate limiting • By using status code 429 server

    can tell that the client has send too many requests in a given amount of time • Send headers like • X-Rate-Limit – number of allowed requests in current period • X-Rate-Remaining – number of remaining requests in the curren period • X-Rate-Limit-Reset – number of seconds left in the period
  124. 176 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)
  125. 177 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/
  126. 178 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
  127. 179 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
  128. 180 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; } }
  129. 181 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
  130. 182 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
  131. 183 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; } }
  132. 184 2) Scanning all packages by default! package fi.company.startingpoint; import

    javax.ws.rs.ApplicationPath; // http://localhost:8080/TestApp/rest/helloworld @ApplicationPath("/rest") public class MyApplication extends Application { }
  133. 188 @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>"; } } }
  134. 189 @Path Example @Path("/users") public 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 + "'}"; } }
  135. 192 @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) { ... } }
  136. 193 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
  137. 194 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
  138. 196 JSR 353 Example String jsonText = "{\"key\": \"value\"}"; JsonReader

    reader = Json.createReader(new StringReader(jsonText)); JsonObject object = reader.readObject(); String name = object.getString("name");
  139. 197 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.
  140. 198 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(); }
  141. 199 Streaming API • Object Model API helps to convert

    JSON directly to generic objects, and requires reading document at once • If documents are large, or efficiency is the key, might be better to use Streaming API • Create a JsonParser, and parse a stream or 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
  142. 200 @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
  143. 201 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; }
  144. 202 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
  145. 205 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 ->
  146. 206 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
  147. 207 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
  148. 208 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!
  149. 210 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; } }
  150. 212 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.
  151. 213 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; } }
  152. 214 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/documentation/2.4/moxy/json 003.htm
  153. 216 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
  154. 217 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 ...
  155. 218 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 204 No Content Succesful request that won't return a body, like for example DELETE (DELETE can be 204 or 200) 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
  156. 219 WebApplicationException • It's possible to throw an Exceptions with

    the status code • throw new WebApplicationException(500); • Also predefined exceptions like • throw new InternalServerErrorException();
  157. 220 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
  158. 221 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; } }
  159. 222 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.
  160. 223 Example of POST @Path("/customers") public class TestResponse { @POST

    @Path("/{id}") 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; } }
  161. 225 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"); } }
  162. 226 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)
  163. 227 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
  164. 228 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; }
  165. 229 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(); }
  166. 230 And using POJOs @GET @Path("/response") @Produces(MediaType.APPLICATION_JSON) public Response response()

    { return Response.ok(new Employee(), MediaType.APPLICATION_JSON).build(); }
  167. 232 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
  168. 234 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>
  169. 235 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>
  170. 238 @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}")
  171. 239 Matrix vs Query params • Query params • http://some.where/thing?paramA=1&paramB=6542

    • Matrix params • http://some.where/thing;paramA=1;paramB=6542
  172. 240 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
  173. 241 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; } }
  174. 242 @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
  175. 243 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
  176. 244 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. "
  177. 245 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