Saturday, January 25, 2014

Adding log4j to your Spring application

If you want to add log4j to your application, here's one way to do it:

First, add the log4j dependency. With gradle, it looks like this:

   compile 'log4j:log4j:1.2.16'

You can find the entries for maven, ivy etc. from this url:

http://mvnrepository.com/artifact/log4j/log4j/1.2.16

Then, you have to either add log4j.properties or log4j.xml to your src/resources folder.

For example, here's one created by the spring mvc project creation wizard in STS:

<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
</layout>
</appender>
<logger name="com.kanjisoft.mvcapp">
<level value="info" />
</logger>
<logger name="org.springframework.core">
<level value="info" />
</logger>
<logger name="org.springframework.beans">
<level value="info" />
</logger>
<logger name="org.springframework.context">
<level value="info" />
</logger>

<logger name="org.springframework.web">
<level value="info" />
</logger>

<root>
<priority value="warn" />
<appender-ref ref="console" />
</root>
</log4j:configuration>

Note how the spring packages are conveniently included. If you want to see them, simply change those ones to "debug". 

References: 
http://www.mkyong.com/spring-mvc/spring-mvc-log4j-integration-example/
http://mvnrepository.com/artifact/log4j/log4j/1.2.16xml version="1.0" encoding="UTF-8"?>



Java client for posting to a Spring restful service

In my last post, http://mcdspringblog.blogspot.com/2014/01/posting-to-restful-service-from-spring.html, I talked about a Java client for retrieving a JSON object from a Spring-based, restful web service In this post, let's discuss how to use the same approach to post a JSON object to the same service.  Again, the client code is based on this post:

http://www.mkyong.com/webservices/jax-rs/restfull-java-client-with-java-net-url/


First, here's the service:

@RequestMapping(value="person3", method=RequestMethod.POST)
@ResponseBody
public Person postPerson(@RequestBody Person person) {
System.out.println("posting " + person.toString());
personService.save(person);
return person;


}

Note how it returns an object in the body of the response (JSON format).

Now let's create the client:

package com.codetutr.client;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import com.codetutr.domain.Person;
import com.google.gson.Gson;

public class NetClientPost {

// http://localhost:8080/api/person/random
public static void main(String[] args) {

 try {


URL url = new URL("http://localhost:8081/spring-mvc-ajax-master/api/person3");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Content-Type", "application/json");
Person person = new Person();
person.setName("John Smith");
person.setAge(33);


String input = new Gson().toJson(person, Person.class);

OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();


BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));

String output;
System.out.println("Output from Server .... \n");
StringBuilder sb = new StringBuilder();
while ((output = br.readLine()) != null) {
System.out.println(output);
sb.append(output);

}


   Gson gson = new Gson();
   Person returnedPerson = gson.fromJson(sb.toString(), Person.class);
   System.out.println("returned person.name: " + returnedPerson.getName() + ", returned person.age: " + returnedPerson.getAge());
 

conn.disconnect();


 } catch (Exception e) {

System.out.println(e.getMessage());
e.printStackTrace();

 }

}

}

And here's the output:

Output from Server .... 


{"name":"John Smith","age":33}


Notes:

I initially got a "415" message from the server, media type not supported. Again the TCP Monitor from eclipse/STS came to the rescue (see my previous post on this). It showed the content-type was getting posted as url-encoded, as opposed to application/json. So, I just added this line:

conn.setRequestProperty("Content-Type", "application/json");

to the client, and we're good.

Tuesday, January 21, 2014

Java client for retrieving a JSON object from a Spring restful service

I recently have been blogging about creating and using restful services in spring, e.g. "http://mcdspringblog.blogspot.com/2014/01/submitting-json-via-jquery-to-restful.html"

So, we know how to create the restful service, using the @RequestBody and @ResponsBody annotations, and how to call it from jQuery. But, what if we want to call it from inside some Java code?

To keep it as simple as possible, we'll use this service to call:

@RequestMapping("person/random")
@ResponseBody
public Person randomPerson() {
return personService.getRandom();

}

After some googling around, it seems that the simplest solution is to use java.net's HttpUrlConnection. We can use that to retrieve the json string from the request, and then convert it to a Person object using Google's Gson. Here's an modified version of a sample client found at http://www.mkyong.com/webservices/jax-rs/restfull-java-client-with-java-net-url/

package com.codetutr.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import com.codetutr.domain.Person;
import com.google.gson.Gson;

public class NetClientGet {

// http://localhost:8080/api/person/random
public static void main(String[] args) {

 try {

URL url = new URL("http://localhost:8080/spring-mvc-ajax-master/api/person/random");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");

if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}

BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));

String output;
System.out.println("Output from Server .... \n");
StringBuilder sb = new StringBuilder();
while ((output = br.readLine()) != null) {
System.out.println(output);
sb.append(output);
}

   Gson gson = new Gson();
   Person person = gson.fromJson(sb.toString(), Person.class);
   System.out.println("Person.name: " + person.getName() + ", person.age: " + person.getAge());
   
conn.disconnect();

 } catch (MalformedURLException e) {

e.printStackTrace();

 } catch (IOException e) {

e.printStackTrace();

 }

}

}

And the output:

Output from Server .... 

{"name":"Robert Ford","age":16}
Person.name: Robert Ford, person.age: 16


Btw, in order to add Gson to the project, I added this line to the gradle build:

   compile 'com.google.code.gson:gson:2.2.4'

Then from the command line, ran this command:

gradle eclipse

Then refreshed the project, then ran a clean and build from STS/Eclipse. Note that I had to do a clean before the build worked correctly.



Wednesday, January 15, 2014

Submitting JSON via jQuery to a restful Spring web service

In one of my recent posts, "Creating a restful JSON web service which sends and receive objects", I talked about a Spring web service which accepts and returns its response as JSON objects.

The Spring-based controller code looks like this:

@RequestMapping(value="person3", method=RequestMethod.POST)
@ResponseBody
public Person postPerson(@RequestBody Person person) {
personService.save(person);
return person;

}

As you can see, it uses both the @RequestBody and @ResponseBody tags to ensure data is both sent and received as JSON. 

This whole experiment was based on a tutorial I was reviewing, http://codetutr.com/2013/04/09/spring-mvc-easy-rest-based-json-services-with-responsebody/, which demonstrates how to use ajax in the client with restful spring services. However, the @ResponseBody example was only mentioned in the example section, and the client was tested using curl as opposed to a jQuery form.

I was curious about how to fill that gap (post JSON from a jQuery form). The ultimate goal was to submit a form which had JSON sent in the body instead of the url-encoded typical query string - i.e. 

{"name":"e","age":"4"}

and not: 

name=e&age=4

The form returned should reflect the name submitted, just as was done with the regular, non-json-encoded post:


So I experimented a little bit and here's the commented code:

// Save Person AJAX Form Submit
$('#newPersonForm').submit(function(e) {
var $this = $(this)  // convert the form to a regular variable (?) 
var obj = form_to_obj($this) // convert it to a javascript object 
var data = JSON.stringify(obj) // here's the magic;  convert the javacript object to JSON 

// I used a generic ajax post here - it was really to ensure the application type is JSON
// I'm sure there are other ways. But it is a nice way to ensure that a) you're posting in ajax and
// b) the block format is easy to follow

$.ajax({
    type: "POST",
    url: "${pageContext.request.contextPath}/api/person3",
    // The key needs to match your method's input parameter (case-sensitive).
    data: data,
    contentType: "application/json; charset=utf-8",
    dataType: "json",

    // the success function takes the response object, which is a person,
   // and writes it to the page
    success: function(person) {  // the response is returned as a javascript object
$('#personFormResponse').text(person.name + ", age: " + person.age);
},
    failure: function(errMsg) {
        alert(errMsg);
    }
});
e.preventDefault(); // prevent actual form submit and page reload
});
});

// function I grabbed from SO to convert to an object
function form_to_obj (selector) {
  var ary = $(selector).serializeArray();
  var obj = {};
  for (var a = 0; a < ary.length; a++) obj[ary[a].name] = ary[a].value;
  return obj;

}

That's about it. I should note that it was invaluable to use the TCP / IP Monitor to see what was being submitted. It helped me to figure out the following bugs:

1) I was submitting a url-encoded query string instead of JSON. 
2) I was getting 400 bad input error - it turned out I was using a function that didn't have the @RequestBody tag
3) I was getting an invalid media type - I had to set the content to application/JSON

You can see in the TCP/IP monitor output below how the submit is including the JSON object in the body. Also, in the response it receives data as JSON. Since the content type is JSON, its's automatically converted to a JSON object for the browser.  











Saturday, January 4, 2014

JQuery, JSON, restful services and Spring MVC - a simple introduction

Knowing how jQuery and css works in the context of a web page is a must-have skill for any web developer. I recently came across a tutorial which has a nice usage of jQuery in its page.  This is the link:

http://codetutr.com/2013/04/09/spring-mvc-easy-rest-based-json-services-with-responsebody/

The page looks like this: 




Here's the page source, with my comments, (I'll use a "//", although it's not valid for html - and supplements the author's own comments in the jQuery). 

// import the jstl taglib
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

// import spring form tag library
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<!DOCTYPE HTML>
<html>
  <head>
    <title>Spring MVC - Ajax</title>

// import jquery library
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <style>

// css - define the background / font for the body
    body { background-color: #eee; font: helvetica; }'

// define container properties
    #container { width: 500px; background-color: #fff; margin: 30px auto; padding: 30px; border-radius: 5px; box-shadow: 5px; }

// "green" class
    .green { font-weight: bold; color: green; }
    .message { margin-bottom: 10px; }

// set up error display
    label { width:70px; display:inline-block;}
    .hide { display: none; }
    .error { color: red; font-size: 0.8em; }
    </style>
  </head>
  <body>
<div id="container">
<h1>Person Page</h1>
<p>This page demonstrates Spring MVC's powerful Ajax functionality. Retrieve a
random person, retrieve a person by ID, or save a new person, all without page reload.
</p>
<h2>Random Person Generator</h2>

// submit to restful service at "person/random" - see jQuery script 
<input type="submit" id="randomPerson" value="Get Random Person" /><br/><br/>

// div to hold the person returned - written to by jQuery code below
<div id="personResponse"> </div>
<hr/>


<h2>Get By ID</h2>

// form to retrieve by id
<form id="idForm">
<div class="error hide" id="idError">Please enter a valid ID in range 0-3</div>
<label for="personId">ID (0-3): </label><input name="id" id="personId" value="0" type="number" />
<input type="submit" value="Get Person By ID" /> <br /><br/>

// area to show person retrieved
<div id="personIdResponse"> </div>
</form>
<hr/>

// new person form
<h2>Submit new Person</h2>
<form id="newPersonForm">
<label for="nameInput">Name: </label>
<input type="text" name="name" id="nameInput" />
<br/>
<label for="ageInput">Age: </label>
<input type="text" name="age" id="ageInput" />
<br/>
<input type="submit" value="Save Person" /><br/><br/>
<div id="personFormResponse" class="green"> </div>
</form>
</div>
<script type="text/javascript">
$(document).ready(function() {

// Random Person AJAX Request
$('#randomPerson').click(function() {

// this is an ajax call - will make a request like this:
// GET /spring-mvc-ajax-master/api/person/random
// Accept: application/json, text/javascript, */*; q=0.01

$.getJSON('${pageContext.request.contextPath}/api/person/random', function(person) {

// set the fields in the web page based on the response
$('#personResponse').text(person.name + ', age ' + person.age);
});
});

// Request Person by ID AJAX

// called on idForm click
$('#idForm').submit(function(e) {

// grab the person's id
var personId = +$('#personId').val();

// validate it
if(!validatePersonId(personId)) 

// invalid - don't propagate the submit and exit by returning false
return false;

// Get the person, this time doing  a ".get". It still receives JSON back,
// although the accept header doesn't specify JSON
// On the wire, it looks like this:

// GET /spring-mvc-ajax-master/api/person/3
// Accept: */*

// Apparently the Jackon handler defaults to JSON,
// Therefore the response can be parsed in the same
// manner as in the above method.
$.get('${pageContext.request.contextPath}/api/person/' + personId, function(person) {
$('#personIdResponse').text(person.name + ', age ' + person.age);
});
e.preventDefault(); // prevent actual form submit
});


// Save Person AJAX Form Submit
$('#randomPerson').click(function() {
$.getJSON('${pageContext.request.contextPath}/api/person/random', function(person) {
$('#personResponse').text(person.name + ', age ' + person.age);
});
});
$('#newPersonForm').submit(function(e) {
// will pass the form data using the jQuery serialize function
// Because it's a post, the data will be passed in the body.

// The serialize function creates a standard URL-encoded string:
// e.g: "name=Tom+Jones&age=57"
// The $(this) must refer to the form which was submitted by clicking on the submit button.

$.post('${pageContext.request.contextPath}/api/person', $(this).serialize(), function(response) {
$('#personFormResponse').text(response);
});
e.preventDefault(); // prevent actual form submit and page reload
});
});

// Neat function which uses label properties as a method to activate them, e.g. show/hide errors.
function validatePersonId(personId) {
console.log(personId);
if(personId === undefined || personId < 0 || personId > 3) {
$('#idError').show();
return false;
}
else {
$('#idError').hide();
return true;
}
}
</script>
  </body>
</html>



Thursday, January 2, 2014

Creating a restful JSON web service which sends and receive objects

I recently wanted to create a restful JSON web service which was able to both receive and return regular java objects.

I was curious how to do it using the @RequestBody and @ResponseBody annotations, since this seemed like the most straightforward approach. Luckily, I found a nice link which basically explains the whole process, and adds in some Javascript for good measure. Here's the link:

http://codetutr.com/2013/04/09/spring-mvc-easy-rest-based-json-services-with-responsebody/

Although the code posted doesn't include using both annotions in the same method, it is explained in the comments section. I implemented it as follows:

@RequestMapping(value="person", method=RequestMethod.POST)
@ResponseBody
public Person postPerson(@RequestBody Person person) {    
    System.out.println("posting " + person.toString());
    personService.save(person);
    return person;


}

Note how both the input and output parameters are Java objects. This serialization to and from JSON in made possible by the inclusion of a jackson-mapper jar file in the classpath. Also, annotations must be turned on, and the request from the application must include a header indicating it's expecting JSON. See the posted link for more details. 

Seeing what the spring container does without walking through the debugger.

If you're curious about what spring is doing, but don't want to walk through the source code as it's executing, one way to do it is to set the debug level for various spring components. For example, the Spring MVC template on STS creates a "log4j.xml" file under "src/main/resources".  All the default levels are set to "info".

However, you can change them to "debug" and you will see a lot more information from the console. For example, if you set the org.springframework.web to "debug", like so:

<logger name="org.springframework.web">
<level value="debug" />

</logger>

you can see the logic of the Spring MVC in action.

DEBUG: org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'appServlet' processing GET request for [/mvctest/]
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Returning handler method [public java.lang.String com.acme.mvctest.HomeController.home(java.util.Locale,org.springframework.ui.Model)]
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'homeController'
DEBUG: org.springframework.web.servlet.DispatcherServlet - Last-Modified value for [/mvctest/] is: -1
INFO : com.acme.mvctest.HomeController - Welcome home! The client locale is en_US.
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'home'
DEBUG: org.springframework.web.servlet.DispatcherServlet - Rendering view [org.springframework.web.servlet.view.JstlView: name 'home'; URL [/WEB-INF/views/home.jsp]] in DispatcherServlet with name 'appServlet'
DEBUG: org.springframework.web.servlet.view.JstlView - Added model object 'serverTime' of type [java.lang.String] to request in view with name 'home'
DEBUG: org.springframework.web.servlet.view.JstlView - Forwarding to resource [/WEB-INF/views/home.jsp] in InternalResourceView 'home'

DEBUG: org.springframework.web.servlet.DispatcherServlet - Successfully completed request