View on GitHub

JSON Service

JSON-RPC library for Java

Download this project as a .zip file Download this project as a tar.gz file

What is JSON Service?

JSON Service is a JSON-RPC server implementation. It supports version 2 of the specification and additionally it provides an implementation of the Service Mapping Description (SMD) specification for providing service metadata to service consumers.

Overview

JSON-RPC is a lightweight Remote Procedure Call protocol that utilises JSON for its messaging envelopes. In a typical situation you will simply need to:

JSON Service performs reflection on any attached classes and uses that information to build both the SMD and enforce method call signatures.

Features

TODO

Dependencies

Maven dependencies that need to be included in the POM file:

                <!-- SLF4J -->
                <dependency>
                    <groupId>org.slf4j</groupId>
                    <artifactId>jcl-over-slf4j</artifactId>
                    <version>1.6.6</version>
                </dependency>
                <dependency>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                    <version>1.6.6</version>
                </dependency>
                <dependency>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                    <version>1.6.6</version>
                </dependency>
                <!-- log4j -->
                <dependency>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                    <version>1.2.17</version>
                </dependency>
                <!-- Jackson -->
                <dependency>
                    <groupId>org.codehaus.jackson</groupId>
                    <artifactId>jackson-core-lgpl</artifactId>
                    <version>1.9.9</version>
                </dependency>
                <dependency>
                    <groupId>org.codehaus.jackson</groupId>
                    <artifactId>jackson-mapper-lgpl</artifactId>
                    <version>1.9.9</version>
                </dependency>
                <!-- Spring Framework (optional) -->
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-web</artifactId>
                    <version>3.1.2.RELEASE</version>
                </dependency>
            

Examples

Example 1: Java Servlet

Download json-service-example1-sources.jar

CalculatorService.java
                public class CalculatorService {

                    @JsonService
                    public Integer add(Integer v1, Integer v2) {

                        return v1 + v2;
                    }

                    @JsonService
                    public Integer subtract(Integer v1, Integer v2) {

                        return v1 - v2;
                    }

                    @JsonService
                    public Integer multiple(Integer v1, Integer v2) {

                        return v1 * v2;
                    }

                    @JsonService
                    public Integer divide(Integer v1, Integer v2) {

                        return v1 / v2;
                    }

                }
            
JsonRpcController.java
                public class JsonRpcController extends HttpServlet {

                    private static JsonServiceRegistry service = new JsonServiceRegistry();

                    static {
                        service.register(CalculatorService.class);
                    }

                    @Override
                    public void doGet(HttpServletRequest request, HttpServletResponse response) {

                        response.setCharacterEncoding("UTF-8");
                        response.setContentType("application/json");

                        service.getServiceMap(CalculatorService.class, response);
                        response.setStatus(200);
                    }

                    @Override
                    public void doPost(HttpServletRequest request, HttpServletResponse response) {

                        String date = (new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z")).format(Calendar.getInstance().getTime());

                        response.setCharacterEncoding("UTF-8");
                        response.setContentType("application/json");
                        response.setHeader("Expires", "Mon, 01 Jan 2000 00:00:00 GMT");
                        response.setHeader("Last-Modified", date);
                        response.setHeader("Cache-Control", "no-cache");

                        service.handle(request, response, CalculatorService.class);
                        response.setStatus(200);
                    }

                }
            
web.xml
                <servlet>
                    <display-name>servlet</display-name>
                    <servlet-name>servlet</servlet-name>
                    <servlet-class>org.stefaniuk.json.service.example1.JsonRpcController</servlet-class>
                </servlet>

                <servlet-mapping>
                    <servlet-name>servlet</servlet-name>
                    <url-pattern>/jsonrpc</url-pattern>
                </servlet-mapping>
            
index.jsp
                require([
                    'dojo/ready',
                    'dojox/rpc/Service',
                    'dojox/rpc/JsonRPC' // JsonRPC has to be loaded too
                ], function(ready, Service) {
                    ready(function() {

                        // create JSON-RPC service
                        service = new Service('jsonrpc');

                        // call JSON-RPC methods
                        service.add(12345, 54321).then(function(result) {
                            console.log('(add)', result);
                        });
                        service.subtract(12345, 54321).then(function(result) {
                            console.log('(subtract)', result);
                        });
                        service.multiple(12345, 54321).then(function(result) {
                            console.log('(multiple)', result);
                        });
                        service.divide(12345, 54321).then(function(result) {
                            console.log('(divide)', result);
                        });

                    });

                });
            

Example 2: Simple Spring Framework integration

Download json-service-example2-sources.jar

CalculatorService.java
                public class CalculatorService {

                    @JsonService
                    public Integer add(Integer v1, Integer v2) {

                        return v1 + v2;
                    }

                    @JsonService
                    public Integer subtract(Integer v1, Integer v2) {

                        return v1 - v2;
                    }

                    @JsonService
                    public Integer multiple(Integer v1, Integer v2) {

                        return v1 * v2;
                    }

                    @JsonService
                    public Integer divide(Integer v1, Integer v2) {

                        return v1 / v2;
                    }

                }
            
JsonRpcController.java
                @Controller
                @RequestMapping(value = "/jsonrpc/*")
                public class JsonRpcController {

                    @Autowired
                    private JsonServiceRegistry jsonService;

                    @RequestMapping(value = "*")
                    public ResponseEntity<String> service(HttpServletRequest request, HttpServletResponse response) throws Exception {

                        return JsonServiceUtil.handle(jsonService, request, response, CalculatorService.class);
                    }

                }
            
service.xml
                <?xml version="1.0" encoding="UTF-8"?>
                <beans xmlns="http://www.springframework.org/schema/beans"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="
                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

                    <!-- JSON Service (JSON-RPC) -->
                    <bean id="jsonService" class="org.stefaniuk.json.service.JsonServiceRegistry">
                        <property name="registry">
                            <list>
                                <value>org.stefaniuk.json.service.example2.CalculatorService</value>
                            </list>
                        </property>
                    </bean>

                </beans>
            
index.jsp
                require([
                    'dojo/ready',
                    'dojox/rpc/Service',
                    'dojox/rpc/JsonRPC' // JsonRPC has to be loaded too
                ], function(ready, Service) {
                    ready(function() {

                        // create JSON-RPC service
                        service = new Service('controller/jsonrpc/');

                        // call JSON-RPC methods
                        service.add(12345, 54321).then(function(result) {
                            console.log('(add)', result);
                        });
                        service.subtract(12345, 54321).then(function(result) {
                            console.log('(subtract)', result);
                        });
                        service.multiple(12345, 54321).then(function(result) {
                            console.log('(multiple)', result);
                        });
                        service.divide(12345, 54321).then(function(result) {
                            console.log('(divide)', result);
                        });

                    });

                });
            

Example 3: Advanced Spring Framework integration

Download json-service-example3-sources.jar

Album.java
                @ModelTable(name = "Album")
                public class Album extends AbstractModel {

                    @ModelColumn(name = "AlbumId")
                    private Integer id;

                    @ModelColumn(name = "Title")
                    private String title;

                    @ModelColumn(name = "ArtistId")
                    private Integer artistId;

                    public Album(Integer id, String title, Integer artistId) {

                        this.id = id;
                        this.title = title;
                        this.artistId = artistId;
                    }

                    public Album(Map<String, Object> row) {

                        setId((Integer) row.get(getColumnName(this.getClass(), "id")));
                        setTitle((String) row.get(getColumnName(this.getClass(), "title")));
                        setArtistId((Integer) row.get(getColumnName(this.getClass(), "artistId")));
                    }

                    public Integer getId() {

                        return id;
                    }

                    public void setId(Integer id) {

                        this.id = id;
                    }

                    public String getTitle() {

                        return title;
                    }

                    public void setTitle(String title) {

                        this.title = title;
                    }

                    public Integer getArtistId() {

                        return artistId;
                    }

                    public void setArtistId(Integer artistId) {

                        this.artistId = artistId;
                    }

                }
            
AlbumDao.java
                public class AlbumDao extends AbstractModelDao<Album> {

                    @Override
                    public Integer create(Album model) {

                        return null;
                    }

                    @Override
                    public Integer update(Album model) {

                        return null;
                    }

                    @Override
                    public Integer update(Album model, Album changed) {

                        return null;
                    }

                    @Override
                    public Integer remove(Album model) {

                        return null;
                    }

                    @Override
                    public List<Album> findAll() {

                        return null;
                    }

                    public List<Album> findByArtistId(Integer artistId) {

                        List<Album> list = new ArrayList<Album>();

                        String sql = String.format("select * from %1$s where ArtistId = " + artistId, TABLE_NAME);
                        List<Map<String, Object>> rows = getJdbcTemplate().queryForList(sql);
                        for(Map<String, Object> row: rows) {
                            list.add(new Album(row));
                        }

                        return list;
                    }

                    @Override
                    public Album findById(Integer id) {

                        return null;
                    }

                    @Override
                    public Integer findIdByModel(Album model) {

                        return null;
                    }

                    @Override
                    public Integer countAll() {

                        return null;
                    }

                }
            
AlbumService.java
                public class AlbumService extends AbstractService<AlbumDao> {

                    @JsonService
                    public List<Album> list(Integer artistId) {

                        return dao.findByArtistId(artistId);
                    }
                }
            
ChinookController.java
                @Controller
                @RequestMapping(value = "/chinook/*")
                public class ChinookController extends AbstractController {

                    @Override
                    @RequestMapping("service/{service}")
                    public ResponseEntity<String> service(HttpServletRequest request, HttpServletResponse response,
                            @PathVariable String service) throws Exception {

                        ResponseEntity<String> re = null;

                        if(service.equals("artist")) {
                            re = handleJsonRpc(request, response, ArtistService.class);
                        }
                        else if(service.equals("album")) {
                            re = handleJsonRpc(request, response, AlbumService.class);
                        }
                        else if(service.equals("track")) {
                            re = handleJsonRpc(request, response, TrackService.class);
                        }

                        return re;
                    }

                }
            
service.xml
                <!-- JSON Service (JSON-RPC) -->
                <bean id="jsonService" class="org.stefaniuk.json.service.JsonServiceRegistry" />

                <!-- artistService -->
                <bean id="artistService" class="org.stefaniuk.json.service.example3.service.ArtistService">
                    <property name="service" ref="jsonService" />
                </bean>

                <!-- albumService -->
                <bean id="albumService" class="org.stefaniuk.json.service.example3.service.AlbumService">
                    <property name="service" ref="jsonService" />
                </bean>

                <!-- trackService -->
                <bean id="trackService" class="org.stefaniuk.json.service.example3.service.TrackService">
                    <property name="service" ref="jsonService" />
                </bean>
            
persistence.xml
                <!-- chinook.sqlite -->
                <bean id="sqliteFileDataSource" class="org.stefaniuk.json.service.example3.datasource.SQLiteFileDataSource" scope="globalSession">
                    <aop:scoped-proxy proxy-target-class="false" />
                </bean>

                <!-- artistDao -->
                <bean id="artistDao" class="org.stefaniuk.json.service.example3.model.ArtistDao">
                    <property name="dataSource" ref="sqliteFileDataSource" />
                </bean>

                <!-- albumDao -->
                <bean id="albumDao" class="org.stefaniuk.json.service.example3.model.AlbumDao">
                    <property name="dataSource" ref="sqliteFileDataSource" />
                </bean>

                <!-- trackDao -->
                <bean id="trackDao" class="org.stefaniuk.json.service.example3.model.TrackDao">
                    <property name="dataSource" ref="sqliteFileDataSource" />
                </bean>
            
index.jsp
                require([
                    'dojo/ready',
                    'dojox/rpc/Service',
                    'dojox/rpc/JsonRPC' // JsonRPC has to be loaded too
                ], function(ready, Service) {
                    ready(function() {

                        // create JSON-RPC services
                        var artistService = new Service('chinook/service/artist');
                        var albumService = new Service('chinook/service/album');
                        var trackService = new Service('chinook/service/track');

                        var count = 1;
                        var artistId = 87;
                        artistService.list().then(function(artists) {
                            albumService.list(artists[artistId].id).then(function(albums) {
                                for(var i in albums) {
                                    var album = albums[i];
                                    (function(album) { // this closure is requried to save a reference to the current album
                                        trackService.list(album.id).then(function(tracks) {
                                            for(var j in tracks) {
                                                var track = tracks[j];
                                                console.log(
                                                    count++, ' - ',
                                                    artists[artistId].name, ' - ',
                                                    album.title, ' - ',
                                                    track.name
                                                );
                                            }
                                        });
                                    })(album); // end: closure
                                }
                            });
                        });

                    });

                });
            

Example 4: Spring Framework, Hibernate and Dojo Store

TODO

Download

json-service-1.1.0.jar
json-service-1.1.0-sources.jar
json-service-1.1.0-javadoc.jar
json-service-example1-sources.jar
json-service-example2-sources.jar
json-service-example3-sources.jar