Ike Lin http://www.ikelin.com tail -f web.log Wed, 12 Jun 2013 06:23:34 +0000 en-US hourly 1 http://wordpress.org/?v=3.5.1 Consume JSON in PUT and POSThttp://www.ikelin.com/consume-json-iput-post/?utm_source=rss&utm_medium=rss&utm_campaign=consume-json-iput-post http://www.ikelin.com/consume-json-iput-post/#comments Wed, 12 Jun 2013 06:23:34 +0000 ilin http://www.ikelin.com/?p=325 I came across some head scratching moments while building JSON RESTful web services in Java. The solution turned out to be quite straight forward once I found it. Hopefully this post can save you some time. My hurdle in particular was consuming JSON as input for HTTP PUT/POST using jQuery and Jersey.

Use Case

Say I need to update a student’s information. Here’s my model in Java:

public class Student {
  private long id;
  private String name;
 
  ...
}

Here’s my model in JavaScript:

{
  id: 102834710293847,
  name: "John Doe"
}

Client Side

By default, jQuery uses application/x-www-form-urlencoded; charset=UTF-8 as content type. This needs to be changed to application/json. jQuery also converts data into a query string by default so this needs to be rectified using JSON.stringify(). The final client side code looks like:

$.ajax({
  url: "/student",
  type: "put",
  data: JSON.stringify(student),
  contentType: "application/json",
});

Server Side

Enable Jersey’s POJO mapping feature in web.xml:

<init-param>
  <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
  <param-value>true</param-value>
</init-param>

The Jersey web service method needs to specify a matching @Consume media type. In this case, application/json:

@PUT
@Path("/student")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response updateStudent(Student student) {
  ...
}

Jersey will then automatically bind the student JSON into a Student class. use Jersey annotations such as @JsonProperty or @JsonIgnore to fine tune the binding processing.

References

]]>
http://www.ikelin.com/consume-json-iput-post/feed/ 0
10 Minutes Setup for Spring, Jersey and MongoDBhttp://www.ikelin.com/10-minutes-setup-for-spring-mvc-jersey-mongodb/?utm_source=rss&utm_medium=rss&utm_campaign=10-minutes-setup-for-spring-mvc-jersey-mongodb http://www.ikelin.com/10-minutes-setup-for-spring-mvc-jersey-mongodb/#comments Sat, 30 Mar 2013 01:09:33 +0000 ilin http://www.ikelin.com/?p=317 A quick setup guide to wire up Jersey and MongoDB for a Spring MVC project. Most existing guides only do one of two or have a Maven POM that imports duplicate (but different versions) of libraries.

  • Spring Data
  • Jersey JSON
  • Jersey Spring
  • Mongo DB

pom.xml

Set the versions.

<properties>
  <spring-version>3.2.2.RELEASE</spring-version>
  <spring-data-mongodb-version>1.2.0.RELEASE</spring-data-mongodb-version>
  <jersey-version>1.17.1</jersey-version>
</properties>

Set dependencies for Spring MVC.

<!-- spring mvc -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>${spring-version}</version>
</dependency>

Set dependencies for Spring Data MongoDB. Need to specify a particular version of spring-tx, otherwise spring-data-mongodb will bring in its own (older) version.

<!-- spring data mongo -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-tx</artifactId>
  <version>${spring-version}</version>
</dependency>
<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-mongodb</artifactId>
  <version>${spring-data-mongodb-version}</version>
</dependency>

Set dependencies for Jersey. Jersey 17.1 depends on Spring 3.1.2 so that will need to be excluded.

<!-- jersey -->
<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-json</artifactId>
  <version>${jersey-version}</version>
</dependency>
<dependency>
  <groupId>com.sun.jersey.contribs</groupId>
  <artifactId>jersey-spring</artifactId>
  <version>${jersey-version}</version>
  <exclusions>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
    </exclusion>
  </exclusions>
</dependency>

web.xml

Configure Spring MVC and Jersey servlets.

<!-- jersey servlet -->
<servlet>
  <servlet-name>jerseySerlvet</servlet-name>
  <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
  <init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <param-value>edu.ucsd.act.service.impl</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
 
<servlet-mapping>
  <servlet-name>jerseySerlvet</servlet-name>
  <url-pattern>/service/*</url-pattern>
</servlet-mapping>

root-context.xml

Setup mongoOperations bean for DAO objects to use

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:p="http://www.springframework.org/schema/p"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:mongo="http://www.springframework.org/schema/data/mongo"
  xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/data/mongo
    http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
 
  <context:component-scan />
 
  <!-- mongo repository -->
  <mongo:mongo host="localhost" port="27017" />
  <mongo:db-factory dbname="bookstore" />
  <bean name="mongoOperations" class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
  </bean>
</beans>

Domain Objects

A sample domain object using JAXB.

@XmlRootElement
public class Author {
  private String name;
}

Data Access Objects

A generic DAO object that uses the MongoDB.

public class AuthorDaoImpl implements AuthorDao {
 
  private static final String COLLECTION = "authors";
 
  @Autowired
  private MongoOperations mongoOperations;
 
  @Override
  public List<Author> getAuthors() {
    return mongoOperations.findAll(Author.class, COLLECTION);
  }
}

JSON Web Service

A generic JAX-RS service interface.

@Path("/bookstore")
public interface BookStoreService {
 
  @Path("/authors")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public List<Author> getAuthors();
 
}
]]>
http://www.ikelin.com/10-minutes-setup-for-spring-mvc-jersey-mongodb/feed/ 0
JavaScript MVC Pros and Conshttp://www.ikelin.com/javascript-mvc-pros-and-con/?utm_source=rss&utm_medium=rss&utm_campaign=javascript-mvc-pros-and-con http://www.ikelin.com/javascript-mvc-pros-and-con/#comments Thu, 14 Mar 2013 06:58:19 +0000 ilin http://www.ikelin.com/?p=305 A list of pros and cons for using JavaScript MVC libraries or frameworks. It’s no silver bullet and there are always trade-offs.

Code Management

Pros
Provides a way to structure or organize client-side code.
Cons
None
Notes
Beware of using minimalist frameworks in a complex application — one can end up with lots of boilerplate code if not careful. Addy Osmani has a good article on picking the right library.

Payload

Pros
Only JSON is passed back to the client. Thus providing a better user experience.
Cons
While subsequent requests are JSON, the initial page load requires the client to download and parse various JavaScript libraries.
Notes
Twitter backed out of client-side MVC because their “time to first tweet” metrics was better with a server-side MVC solution.

Progressive Enhancement

Pros
None
Cons
Lots of extra work
Notes
Developers will need to build server-side rendering if JavaScript is disabled on the client-side. If the server language is supported by the JavaScript template engine, then you only need to maintain one template. Otherwise, you’ll need to maintain two templates.
]]>
http://www.ikelin.com/javascript-mvc-pros-and-con/feed/ 0
FullCalendar Resource Day View Bughttp://www.ikelin.com/fullcalendar-resource-day-view-bug/?utm_source=rss&utm_medium=rss&utm_campaign=fullcalendar-resource-day-view-bug http://www.ikelin.com/fullcalendar-resource-day-view-bug/#comments Wed, 30 Jan 2013 02:22:25 +0000 ilin http://www.ikelin.com/?p=300 Thanks to Rachel Z., who pointed out a bug in the FullCalendar Resource Day View. In the resource day view, if one moves an event from one resource to another resource and wants to revert the move, the event object did not contain the original resource id.

I’ve updated src/resource/ResourceEventRenderer.js so the event object now contains oldResourceId. What one will have to do in event function is to remember to set the event’s resource to the old one before calling revertFunc(). I realize this is not ideal, but it is better than refactoring the event*() method signatures and forcing everyone to update their code.

  $('#calendar').fullCalendar({
    ...
    eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc) {
      if (!confirm("Are you sure?")) {
        event.resourceId=event.oldResourceId;  // add this to revert
        revertFunc();
      }
    }
     ...
  }

You can find the latest code on github.

]]>
http://www.ikelin.com/fullcalendar-resource-day-view-bug/feed/ 0
Bootstrap Datepickerhttp://www.ikelin.com/bootstrap-datepicker/?utm_source=rss&utm_medium=rss&utm_campaign=bootstrap-datepicker http://www.ikelin.com/bootstrap-datepicker/#comments Tue, 30 Oct 2012 09:01:22 +0000 ilin http://www.ikelin.com/?p=282 Looking for a datepicker widget for Twitter Bootstrap?


Existing Bootstrap Datepicker Widgets

High on top of Google’s search result was Stefan Petre’s implementation. But I noticed this particular implementation as well as its forked implementation all suffered from a date selection bug when crossing years. For example, If I selected 01/01/13, then select 12/31/12 without going to the previous month, I get 03/03/13 as the selected date instead.

Another bug with these implementations has to do with dynamically adding and removing datepicker input fields via AJAX. This happens when you have a modal dialog box that contains a datepicker input field.  My hunch is that each instance of datepicker input is appended to the end of the body tag, and when dynamically adding or removing datepicker inputs, the multiple instances of datepicker inputs were not managed properly.  Thus on the second try, an error about date.split(format.separator) will appear.  I changed .appendTo('body') to .appendTo(this.element) on line 41 of the bootstrap-datepicker.js and this error went away.

jQuery UI Datepicker

I have used jQuery UI Datepicker on many projects and loved it. At around 50KB minimized, it’s not the smallest one out there, but it’s a mature widget that doesn’t suffer from previously mentioned bugs.  So next approach was to find a jQuery UI Datepicker with Twitter Bootstrap theme. The first one I came across was the jQuery UI Bootstrap by Addy Osmani.  But I personally felt this datepicker widget was still looking too jQuery UI-ish with its rounded-corner title. The closest one to what I want was from Scott Torborg, but I really didn’t like the arrows for month and year.

DYI

So, after trying to avoid actual work, I came up with this DYI version of jQuery UI Datepicker with Twitter Bootstrap theme. Source and demo can be found on GitHub.

The best part is that I didn’t have to change much on the JS side, so all of existing datepicker’s options such as button panel or multiple calendars still work.

]]>
http://www.ikelin.com/bootstrap-datepicker/feed/ 0