Giter VIP home page Giter VIP logo

jsonrpc4j's Introduction

JSON-RPC for Java

This project aims to provide the facility to easily implement JSON-RPC for the java programming language. jsonrpc4j uses the Jackson library to convert java objects to and from json objects (and other things related to JSON-RPC).

Javadoc Download Travis CI GitHub commits

Features Include:

  • Streaming server (InputStream \ OutputStream)
  • HTTP Server (HttpServletRequest \ HttpServletResponse)
  • Portlet Server (ResourceRequest \ ResourceResponse)
  • Socket Server (StreamServer)
  • Integration with the Spring Framework (RemoteExporter)
  • Streaming client
  • HTTP client
  • Dynamic client proxies
  • Annotations support
  • Custom error resolving
  • Composite services

Maven

This project is built with Maven. Be sure to check the pom.xml for the dependencies if you're not using maven. If you're already using spring you should have most (if not all) of the dependencies already - outside of maybe the Jackson Library. Jsonrpc4j is available from the maven central repo. Add the following to your pom.xml if you're using maven:

In <dependencies>:

	<!-- jsonrpc4j -->
	<dependency>
		<groupId>com.github.briandilley.jsonrpc4j</groupId>
		<artifactId>jsonrpc4j</artifactId>
		<version>1.6</version>
	</dependency>

or with gradle:

    implementation('com.github.briandilley.jsonrpc4j:jsonrpc4j:1.6')

If you want to just download the projects output JAR and it's dependencies you can do it over at the Maven repository.

JSON-RPC specification

The official source for the JSON-RPC 2.0 specification. The guys over at json-rpc google group seem to be fairly active, so you can ask clarifying questions there.

Streaming server and client

Jsonrpc4j comes with a streaming server and client to support applications of all types (not just HTTP). The JsonRpcClient and JsonRpcServer have simple methods that take InputStreams and OutputStreams. Also in the library is a JsonRpcHttpClient which extends the JsonRpcClient to add HTTP support.

Spring Framework

jsonrpc4j provides a RemoteExporter to expose java services as JSON-RPC over HTTP without requiring any additional work on the part of the programmer. The following example explains how to use the JsonServiceExporter within the Spring Framework.

Create your service interface:

package com.mycompany;
public interface UserService {
    User createUser(String userName, String firstName, String password);
    User createUser(String userName, String password);
    User findUserByUserName(String userName);
    int getUserCount();
}

Implement it:

package com.mycompany;
public class UserServiceImpl
    implements UserService {

    public User createUser(String userName, String firstName, String password) {
        User user = new User();
        user.setUserName(userName);
        user.setFirstName(firstName);
        user.setPassword(password);
        database.saveUser(user);
        return user;
    }

    public User createUser(String userName, String password) {
        return this.createUser(userName, null, password);
    }

    public User findUserByUserName(String userName) {
        return database.findUserByUserName(userName);
    }

    public int getUserCount() {
        return database.getUserCount();
    }

}

Configure your service in spring as you would any other RemoteExporter:

<?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-2.5.xsd">

    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

    <bean id="userService" class="com.mycompany.UserServiceImpl">
    </bean>

    <bean name="/UserService.json" class="com.googlecode.jsonrpc4j.spring.JsonServiceExporter">
        <property name="service" ref="userService"/>
        <property name="serviceInterface" value="com.mycompany.UserService"/>
    </bean>

</beans>

Your service is now available at the URL /UserService.json. Type conversion of JSON->Java and Java->JSON will happen for you automatically. This service can be accessed by any JSON-RPC capable client, including the JsonProxyFactoryBean, JsonRpcClient and JsonRpcHttpClient provided by this project:

<?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.xsd">

    <bean  class="com.googlecode.jsonrpc4j.spring.JsonProxyFactoryBean">
        <property name="serviceUrl" value="http://example.com/UserService.json"/>
        <property name="serviceInterface" value="com.mycompany.UserService"/>
    </bean>

<beans>

In the case that your JSON-RPC requires named based parameters rather than indexed parameters an annotation can be added to your service interface (this also works on the service implementation for the ServiceExporter):

package com.mycompany;
public interface UserService {
    User createUser(@JsonRpcParam(value="theUserName") String userName, @JsonRpcParam(value="thePassword") String password);
}

By default all error message responses contain the the message as returned by Exception.getmessage() with a code of 0. This is not always desirable. jsonrpc4j supports annotated based customization of these error messages and codes, for example:

package com.mycompany;
public interface UserService {
    @JsonRpcErrors({
        @JsonRpcError(exception=UserExistsException.class,
            code=-5678, message="User already exists", data="The Data"),
        @JsonRpcError(exception=Throwable.class,code=-187)
    })
    User createUser(@JsonRpcParam(value="theUserName") String userName, @JsonRpcParam(value="thePassword") String password);
}

The previous example will return the error code -5678 with the message User already exists if the service throws a UserExistsException. In the case of any other exception the code -187 is returned with the value of getMessage() as returned by the exception itself.

Auto Discovery With Annotations

Spring can also be configured to auto-discover services and clients with annotations.

To configure auto-discovery of annotated services first annotate the service interface:

@JsonRpcService("/path/to/MyService")
interface MyService {
... service methods ...
}

Next annotate the implementation of the service interface;

@AutoJsonRpcServiceImpl
class MyServiceImpl {
... service methods' implementations ...
}

and use the following configuration to allow spring to find the implementation that you would like to expose:

<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.0.xsd">

  <bean class="com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImplExporter"/>

  <bean class="com.mycompany.MyServiceImpl" />

</beans>

Configuring a client is just as easy:

<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.0.xsd">

  <bean class="com.googlecode.jsonrpc4j.spring.AutoJsonRpcClientProxyCreator">
    <property name="baseUrl" value="http://hostname/api/" />
    <property name="scanPackage" value="com.mycompany.services" />
  </bean>

</beans>

Where the baseUrl is added to the front of the path value provided by the JsonRpcService annotation and scanPackage tells spring which packages to scan for services.

Without the Spring Framework

jsonrpc4j can be used without the spring framework as well. In fact, the client and server both work in an Android environment.

Client

Here's an example of how to use the client to communicate with the JSON-RPC service described above:

JsonRpcHttpClient client = new JsonRpcHttpClient(
    new URL("http://example.com/UserService.json"));

User user = client.invoke("createUser", new Object[] { "bob", "the builder" }, User.class);

Or, the ProxyUtil class can be used in conjunction with the interface to create a dynamic proxy:

JsonRpcHttpClient client = new JsonRpcHttpClient(
    new URL("http://example.com/UserService.json"));

UserService userService = ProxyUtil.createClientProxy(
    getClass().getClassLoader(),
    UserService.class,
    client);

User user = userService.createUser("bob", "the builder");

server

The server can be used without spring as well:

// create it
JsonRpcServer server = new JsonRpcServer(userService, UserService.class);

After having created the server it's simply a matter of calling one of the handle(...) methods available. For example, here's a servlet using the very same UserService:

class UserServiceServlet
    extends HttpServlet {

    private UserService userService;
    private JsonRpcServer jsonRpcServer;

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
        jsonRpcServer.handle(req, resp);
    }

    public void init(ServletConfig config) {
        //this.userService = ...
        this.jsonRpcServer = new JsonRpcServer(this.userService, UserService.class);
    }

}

Composite Services

Multiple services can be combined into a single server using one of the ProxyUtil::createCompositeService(...) methods. For example:

UserverService userService = ...;
ContentService contentService = ...;
BlackJackService blackJackService = ...;

Object compositeService = ProxyUtil.createCompositeServiceProxy(
    this.getClass().getClassLoader(),
    new Object[] { userService, contentService, blackJackService},
    new Class<?>[] { UserService.class, ContentService.class, BlackJackService.class},
    true);

// now compositeService can be used as any of the above service, ie:
User user = ((UserverService)compositService).createUser(...);
Content content =  ((ContentService)compositService).getContent(...);
Hand hand = ((BlackJackService)compositService).dealHand(...);

This can be used in conjunction with the JsonRpcServer to expose the service methods from all services at a single location:

JsonRpcServer jsonRpcServer = new JsonRpcServer(compositeService);

A spring service exporter exists for creating composite services as well named CompositeJsonServiceExporter.

Streaming (Socket) Server

A streaming server that uses Sockets is available in the form of the StreamServer class. It's use is very straightforward:

// create the jsonRpcServer
JsonRpcServer jsonRpcServer = new JsonRpcServer(...);

// create the stream server
int maxThreads = 50;
int port = 1420;
InetAddress bindAddress = InetAddress.getByName("...");
StreamServer streamServer = new StreamServer(
    jsonRpcServer, maxThreads, port, bindAddress);

// start it, this method doesn't block
streamServer.start();

and when you're ready to shut the server down:

// stop it, this method blocks until
// shutdown is complete
streamServer.stop();

Of course, this is all possible in the Spring Framework as well:

    <bean id="streamingCompositeService" class="com.googlecode.jsonrpc4j.spring.CompositeJsonStreamServiceExporter">
        <!-- can be an IP, hostname or omitted to listen on all available devices -->
        <property name="hostName" value="localhost"/>
        <property name="port" value="6420"/>
        <property name="services">
        	<list>
	        	<ref bean="userService" 	/>
	        	<ref bean="contentService" 	/>
	        	<ref bean="blackJackService" 	/>
        	</list>
        </property>
    </bean>
}

JsonRpcServer settings explained

The following settings apply to both the JsonRpcServer and JsonServiceExporter:

  • allowLessParams - Boolean specifying whether or not the server should allow for methods to be invoked by clients supplying less than the required number of parameters to the method.
  • allowExtraParams - Boolean specifying whether or not the server should allow for methods to be invoked by clients supplying more than the required number of parameters to the method.
  • rethrowExceptions - Boolean specifying whether or not the server should re-throw exceptions after sending them back to the client.
  • backwardsComaptible - Boolean specifying whether or not the server should allow for jsonrpc 1.0 calls. This only includes the omission of the jsonrpc property of the request object, it will not enable class hinting.
  • errorResolver - An implementation of the ErrorResolver interface that resolves exception thrown by services into meaningful responses to be sent to clients. Multiple ErrorResolvers can be configured using the MultipleErrorResolver implementation of this interface.
  • batchExecutorService - A configured ExecutorService to use for parallel JSON-RPC batch processing. By default batch requests are handled sequentially.

Server Method resolution

Methods are resolved in the following way, each step immediately short circuits the process when the available methods is 1 or less.

  1. If a method has the @JsonRpcMethod annotation, then if the annotation value has the same name as the request method, it is considered. If the annotation has required set to true, then the Java method name is not considered.
  2. Otherwise, all methods with the same name as the request method are considered.
  3. If allowLessParams is disabled methods with more parameters than the request are removed
  4. If allowExtraParams is disabled then methods with less parameters than the request are removed
  5. If either of the two parameters above are enabled then methods with the lowest difference in parameter count from the request are kept
  6. Parameters types are compared to the request parameters and the method(s) with the highest number of matching parameters is kept
  7. If there are multiple methods remaining then the first of them are used

jsonrpc4j's method resolution allows for overloaded methods sometimes. Primitives are easily resolved from json to java. But resolution between other objects are not possible.

For example, the following overloaded methods will work just fine:

json request:

{"jsonrpc":"2.0", "id":"10", "method":"aMethod", "params":["Test"]}

java methods:

public void aMethod(String param1);
public void aMethod(String param1, String param2);
public void aMethod(String param1, String param2, int param3);

But the following will not:

json request:

{"jsonrpc":"2.0", "id":"10", "method":"addFriend", "params":[{"username":"example", "firstName":"John"}]}

java methods:

public void addFriend(UserObject userObject);
public void addFriend(UserObjectEx userObjectEx);

The reason being that there is no efficient way for the server to determine the difference in the json between the UserObject and UserObjectEx Plain Old Java Objects.

Custom method names

In some instances, you may need to expose a JsonRpc method that is not a valid Java method name. In this case, use the annotation @JsonRpcMethod on the service method. You may also use this annotation to disambiguate overloaded methods by setting the required property on the annotation to true.

@JsonRpcService("/jsonrpc")
public interface LibraryService {
    @JsonRpcMethod("VideoLibrary.GetTVShows")
    List<TVShow> fetchTVShows(@JsonRpcParam(value="properties") final List<String> properties);
}
{"jsonrpc":"2.0", "method": "VideoLibrary.GetTVShows", "params": { "properties": ["title"] }, "id":1}

jsonrpc4j's People

Contributors

andponlin avatar anysoft avatar brettwooldridge avatar briandilley avatar candrews avatar crow-misia avatar cyb3r4nt avatar deltaflight avatar donequis avatar dzolo avatar gaborbernat avatar indvd00m avatar joincamp avatar kostapc avatar mbertram avatar mcree avatar mirvnillith avatar mslipper avatar onnokort avatar phantomread1 avatar rbogie avatar shredder121 avatar sumitsharma0999 avatar superquadratic avatar vm-001 avatar vtintillier avatar wuwen5 avatar yin avatar zetten avatar zzashpaupat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jsonrpc4j's Issues

Exception does not propegate to the client from the server (InvocationTargetException)

When I throw a RuntimeException from the server it does not fully extract the source exception and such sends an InvocationTargetException to the client. However, this cannot be instantianated, so the client throws:

 WARNING: Unable to find a suitable constructor for        java.lang.reflect.InvocationTargetException
 Exception in thread "main" com.googlecode.jsonrpc4j.JsonRpcClientException: null
    at        com.googlecode.jsonrpc4j.DefaultExceptionResolver.createJsonRpcClientException(DefaultExceptionResolver.java:80)

Here's a quick test project (https://github.com/gaborbernat/json4j-rpc-test). You need to run:

./gradlew server:appRun
./gradlew client:run

Any ideas what's wrong and how to fix it?

Thanks,

Remove superfluous locks

Class com.googlecode.jsonrpc4j.ReadContext isn't cached now so for performance reason it may be a good idea to remove synchronized from static getReadContext() method. Also I have not found cases of concurrent reading from NoCloseInputStream, so I think there are no reasons to use synchronized methods.

Impossible to choose which exceptions to log

In JsonRpcBasicServer.java the following code appears at the end of handleObject()

// log and potentially re-throw errors
    if (thrown!=null) {
        if (LOGGER.isLoggable(exceptionLogLevel)) {
            LOGGER.log(exceptionLogLevel, "Error in JSON-RPC Service", thrown);
        }
        if (rethrowExceptions) {
            throw new RuntimeException(thrown);
        }
    }
    return returnCode;
}

This means that the jsonrpc is constantly logging exceptions that no one cares about. As a result there is no way to tell it not to fill the log with exceptions other than switching off all log messages for that log level which is not sensible as you need some of them.

Can you throw the exception upwards so we can decide whether to log it.

// log and potentially re-throw errors
if (thrown!=null) {
if (rethrowExceptions) {
throw new RuntimeException(thrown);
}
}
return returnCode;
}

Move javax.* into derived JsonRpcServer class?

I'm using JsonRpcClient - actually a derived class that connects via OkHttp - in an Android app to connect to a JSON-RPC server.

To allow the instrumentation tests to run without network interaction, I mocked out the actual HTTP connection cruft and replaced it with a fake HttpUrlConnection implementation that uses Java's PipedInputStream and PipedOutputStream to connect to a JsonRpcServer.

This works all fine, except that I had to copy the original JsonRpcServer into my own project and remove several handle() methods that would not compile on Android because of missing javax.* imports.

Since the code otherwise seems to be pretty clean (except the spring part which I don't use either obviously), maybe one could move a specialized / derived version of JsonRpcServer into spring/ as well and add the javax.* dependent methods there? Maybe the project could also get mavenized, with a jsonrpc4j-core and a jsonrpc4j-spring part...?

NullPointerException with CompositeService when calling method inherited from super-interface

Following the example in the documentation, a composite server is created as:

    UserverService userService = ...;
    ContentService contentService = ...;
    BlackJackService blackJackService = ...;

    Object compositeService = ProxyUtil.createCompositeServiceProxy(
        this.getClass().getClassLoader(),
        new Object[] { userService, contentService, blackJackService},
        new Class<?>[] { UserService.class, ContentService.class, BlackJackService.class},
        true);

And then the corresponding client-side code is:

    UserverService userService = ProxyUtil.createClientProxy(
                UserverService.class.getClassLoader(), UserverService.class,
                jsonRpcClient, socket);
    ContentService contentService = ...;
    BlackJackService blackJackService = ...;

    Object compositeService = ProxyUtil.createCompositeServiceProxy(
        this.getClass().getClassLoader(),
        new Object[] { userService, contentService, blackJackService},
        new Class<?>[] { UserService.class, ContentService.class, BlackJackService.class},
        true);

    // now compositeService can be used as any of the above service, ie:
    User user = ((UserverService)compositService).createUser(...);
    Content content =  ((ContentService)compositService).getContent(...);
    Hand hand = ((BlackJackService)compositService).dealHand(...);  

Now, suppose both UserverService and ContentService extend a super-interface OperationService, which declares a method getOperation();
Then both calls:

    int id = ((UserverService)compositService).getOperation();
    int id = ((ContentService)compositService).getOperation();

will throw the following exception:

java.lang.NullPointerException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.googlecode.jsonrpc4j.ProxyUtil$1.invoke(ProxyUtil.java:103)
at com.sun.proxy.$Proxy6.getOperation(Unknown Source)

[Enhancement] ProxyUtil support for notifications

Currently ProxyUtil can not be used for JSON-RPC notifications, as calling any method on the service will always block waiting for a response.

Would be really nice to be able to create a client proxy for calling methods on the server that does not block for responses.

Avoid chunked encoding by calling setContentLength() before writing to output stream

I'm working on a Java-based JSON RPC server that will be compatible with the Bitcoin Core JSON RPC implementation. The command line client bitcoin-cli is the canonical Bitcoin RPC client and returns error: no response from server when talking to my server based on jsonrpc4j.

I spent some time debugging and determined that bitcoin-cli can't handle an HTTP chunked response.

I changed:

int result = handle(input, output);

to:

ByteArrayOutputStream bufOut = new ByteArrayOutputStream(1024);
int result = handle(input, bufOut);
response.setContentLength(bufOut.size());   // Set content-length avoid chunked encoding
output.write(bufOut.toByteArray());

in JsonRpcServer.java and that solved the problem.

Should we make a change like the above to completely disable chunked encoding or should we make it configurable? I'd love to see this fix go in to 1.2.0 and am willing to submit a pull request once we agree on the right way to solve the problem.

Configurable exceptionLogLevel in spring.AutoJsonRpcServiceExporter

What steps will reproduce the problem?

  1. Throw an exception in a service
  2. See WARNING log entry in server log

What is the expected output? What do you see instead?

I would like to be able to set the JsonRpcServer's exceptionLogLevel via spring.AutoJsonRpcServiceExporter

What version of the product are you using? On what operating system?
0.29-SNAPSHOT

Please provide any additional information below.

http://code.google.com/p/jsonrpc4j/issues/detail?id=56

How to serialize/de-serialize custom Exceptions?

I have one exception in my interface that has it's own data. How am I supposed to get that to work? The additional fields on the exceptions are not serialized and part of the error structure. From what I've seen from the code, I could possibly write an ErrorResolver that creates a custom serialization of the exception on the server side, and then write an ExceptionResolver that rebuilds the exception on the client side?

Maybe all fields on exceptions should be serialized and not only the message part?

JSON-RPC GET handling has an extra URL decode on params

When the params for a JSON-RPC request are URL encoded, the are Base64 encoded, and the URL encoded to make the Base64 URL safe (see http://jsonrpc.org/historical/json-rpc-over-http.html#encoded-parameters). In JsonRpcServer.createInputStream, the params argument has already been URL decoded, and then it is converted from Base64 to a String, however, that string is then URL decoded again. This causes any URL unsafe characters in the params to be changed, corrupting the params. I've attached a patch in the next comment (hopefully)

Using jackson-datatype-hibernate with jsonrpc4j

Does jsonrpc4j work with the jackson-datatype-hibernate module for lazy loading support.

  • Registering a HibernateAwareObjectMapper still throws the following error:
    java.lang.IllegalArgumentException: failed to lazily initialize a collection of role:

Do one have to register the ObjectMapper specifically for jsonrpc4j?

// Regards

JsonMappingException when the client close the connection using the StreamServer

com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
at [Source: com.googlecode.jsonrpc4j.NoCloseInputStream@7de4e3e4; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:3036)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2978)
at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:1737)
at com.googlecode.jsonrpc4j.JsonRpcServer.handle(JsonRpcServer.java:224)
at com.googlecode.jsonrpc4j.StreamServer$Server.run(StreamServer.java:214)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:695)

in jackson library if it reads null token follow null token. it will throw the exception. should it check the connection status before parse the json stream?

protected JsonToken _initForReading(JsonParser jp)
throws IOException, JsonParseException, JsonMappingException
{
/* First: must point to a token; if not pointing to one, advance.
* This occurs before first read from JsonParser, as well as
* after clearing of current token.
/
JsonToken t = jp.getCurrentToken();
if (t == null) {
// and then we must get something...
t = jp.nextToken();
if (t == null) {
/
[JACKSON-546] Throw mapping exception, since it's failure to map,
* not an actual parsing problem
*/
throw JsonMappingException.from(jp, "No content to map due to end-of-input");
}
}
return t;
}

Turing on default typing breaks jsonrpc

Very cool project, we are very close to getting things working. However, we have several areas where we have polymorphic types. We are injecting our own ObjectMapper into Jsonrpc4j with "enableDefaultTyping(DefaultTyping.NON_FINAL)

The type information is tripping up because the request parameters are being mapped to a JSON node tree via the valueToTree method.

There is a related issue on the Jackson site :

FasterXML/jackson-databind#353

Is there any possible workaround for this issue?

how do I create/customise the jackson Objectmapper?

first of all, thank you for this project, its very helpful for me.
I'm using spring, and I need to be able to customise the objectMapper instance in use (or provide a new one), but I'm not entirely sure how to achieve it.
I need to add custom Modules/serialisers, and configuration. It would be especially nice to be able to configure an XmlMapper in place of the json output objectmapper too. is it possible?

hope you can help.
Cheers

Transactional support

Hi there,

I'm writing an application and I'd love to use JSON-RPC 4J. The app has two parts, a JSON-RPC and a client. I'd like the client to connect, make several RPC calls (using the streams version), and then disconnect. If anything goes wrong, then I'd like to have wrapped it in a transaction, and roll the whole thing back.

Could you give me a pointer or suggestion on how I might do this?

Alex

JsonRpcHttpClient always sets its own Content-Type header even if one was specified.

What steps will reproduce the problem?
Try using the http client against XBMC:
Map<String,String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");

JsonRpcHttpClient client = new JsonRpcHttpClient(
new URL("http://xbmc:8080/jsonrpc"),headers);

client.invoke("GUI.ShowNotification", new Object[] {"Test", "Hello world"});

What is the expected output? What do you see instead?
Expexted a notification but geting a 415 http error response code.

Please provide any additional information below.
Fixed it by adding a check to the http client for a content type.
From:
con.setRequestProperty("Content-Type", "application/json-rpc");

To:
if(!headers.containsKey("Content-Type")) {
con.setRequestProperty("Content-Type", "application/json-rpc");
}

http://code.google.com/p/jsonrpc4j/issues/detail?id=67

Do not throw/report Throwable

Hi,

first of all... great and simple library.

But no library is perfect ;) so I have to report a code-smell.

Using "Throwable" as reported exceptions is dangerous. Since Error-Classes also inherit from Throwable handling the reported "Throwable" could lead to hide Errors like OutOfMemoryError.

Since you usually are not able to correct the operation in cases such an error is thrown the errors has to crash the application.

Please report the concrete exception or implement your own exception hierarchy based on "Exception" or "RuntimeException".

Server unusable on Android

Hello,

I was trying to run a basic StreamServer on Android. As I understand from the readme, this should be possible.

But when Android's class loader encounters JsonRpcServer, the whole application blows up because of dependencies on classes from javax (portlet and servlet) namespace.

So what can be done to go around that and launch a server on Android? Do I have to make a fork and cut all JavaEE stuff out? Will it work then?

Regards,
Michal

JSON RPC over Spring RestTemplate

Hi!
How about to add implementation using Spring RestTemplate as mapping and transport layer for requests?

Yours respectfully, Toha.

Compiler time error while using JsonRpcServer with HttpServletRequest and HttpServletResponse

I am using jsonrpc4j 1.1 using following dependency with maven.

<dependency>
     <groupId>com.github.briandilley.jsonrpc4j</groupId>
     <artifactId>jsonrpc4j</artifactId>
     <version>1.1</version>
</dependency>

And I am writing simple Servlet to create JsonRpcServer as follows.

@WebServlet
public class SampleServer extends HttpServlet {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Service service;
    private JsonRpcServer jsonRpcServer;


    protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
        jsonRpcServer.handle(req, resp);
    }

    public void init(ServletConfig config) {
        this.service = new Service();
        this.jsonRpcServer = new JsonRpcServer(this.service, ServiceInterface.class);
    }
}

I know that jsonRpcServer have this method.

public void handle(HttpServletRequest request, HttpServletResponse response){
...
}

even though I am getting compile time error in eclipse which says,
The type javax.portlet.ResourceResponse cannot be resolved. It is indirectly referenced from required .class files
json-rpc-eclipse-error

I have servlet api in my eclipse classpath, second thing I am not using anywhere javax.portlet.ResourceResponse.

I have also searched a lot on Google, but can't find any answer. Is this bug? Can anybody help me. Any help would be very appreciated.

Thanks in advance.

Regards,
Vishal Z.

Log incoming and outgoing JSON

I couldn't find a way of switching on request/response output. The JsonRpcServer does not give you access to the ObjectMapper so it is difficult to debug or record what goes through the server especially if you are not using Spring (which I am not (in this case)).

In order to log incoming and out going packets I needed to add the following hack but it would be nice if there was a simple switch.

public class MyServletJsonRpc extends HttpServlet {
   private MyService myService;
   private JsonRpcServer jsonRpcServer;

   @Override
   protected void doPost(HttpServletRequest request
                      , HttpServletResponse response) throws IOException {
      jsonRpcServer.handle(request, response);
   }
   @Override
   public void init(ServletConfig config) {
       myService = new MyServiceImpl();
       ObjectMapper mapper = new MyObjectMapper(null, null, null);
       jsonRpcServer = new MyJsonRpcServer(mapper, myService, null);
       jsonRpcServer.set...
   }
}

class MyObjectMapper extends ObjectMapper {
    private static final Logger L = LoggerFactory.getLogger(MyObjectMapper.class);

    public MyObjectMapper(JsonFactory jf, DefaultSerializerProvider sp, DefaultDeserializationContext dc) {
        super(jf, sp, dc);
    }

    @Override
    public void writeValue(OutputStream out, Object value) throws IOException, JsonGenerationException, JsonMappingException {
        super.writeValue(out, value);
        L.info("Out: " + writeValueAsString(value));
    }
}

class MyJsonRpcServer extends JsonRpcServer {
    private static final Logger L = LoggerFactory.getLogger(MyJsonRpcServer.class);

    public MyJsonRpcServer(ObjectMapper mapper, Object handler, Class<?> remoteInterface) {
        super(mapper, handler, remoteInterface);
    }

    @Override
    public void handleNode(JsonNode node, OutputStream ops) throws IOException {
        L.info("In: " + (node == null ? "(null)" : node.toString()));
        super.handleNode(node, ops);
    }
}

More solutions might present themselves here: http://stackoverflow.com/questions/32268009/logging-json-rpc-calls-using-jsonrpc4j

Issues deserializing scala collections

I'm providing a scala-aware mapper to JSON RPC but finding that its impossible to deserialize return values (via JsonRpcHttpClient) if method returns scala collection types. I've checked and found that the same mapper object can deserialize JSON into the same scala list type.

So... I did some digging and found that using

 method.getReturnType()

as the type parameter to mapper instead of

method.getGenericReturnType()

Seems to solve this issue. i.e. use

ProxyUtil::createClientProxy() ... 
  ... Class[_] clazz = method.getReturnType()
  ... invoke(... clazz ...)

JsonRpcClient::readResponse() ...
  ...
  val tokens = mapper.treeAsTokens(jsonObject.get("result"))
  return mapper.readValue(tokens, clazz).asInstanceOf[Object]

instead of

ProxyUtil::createClientProxy() ... 
  ... Type returnJavaType = method.getGenericReturnType() 
  ... invoke(... returnJavaType ...)
JsonRpcClient::readResponse() ...
        JsonParser returnJsonParser = mapper.treeAsTokens(jsonObject.get("result"));
        JavaType returnJavaType = TypeFactory.defaultInstance().constructType(returnType);          
        return mapper.readValue(returnJsonParser, returnJavaType);

Is there any reason to prefer using getGenericReturnType? Or can a pull request be submitted to replace Type with Class<?> wherever return types are used?

NB. I thought I could fix this by simply providing my own client proxy to use method.getReturnType() (which returns a class). However, although there's a JsonRpcClient::invoke method that takes a Class<?>, this is downcast to a Type, and, I think, by then its not possible to get mapper to instantiate the scala collection class using either:

mapper.readValue(returnJsonParser, );

mapper.readValue(returnJsonParser, <Class[] >);

:( So... better to pass around Class than Type. Any reason not to?

Doggie contrstuctor

in version 1.1

/**
 * Creates the server with a default {@link ObjectMapper} delegating
 * all calls to the given {@code handler} {@link Object} but only
 * methods available on the {@code remoteInterface}.
 *
 * @param handler the {@code handler}
 * @param remoteInterface the interface
 */
public JsonRpcServer(Object handler, Class<?> remoteInterface) {
    this(new ObjectMapper(), handler, null);
}

Is this right? remoteInterface isn't being used! Surely this should be:

public JsonRpcServer(Object handler, Class<?> remoteInterface) {
    this(new ObjectMapper(), handler, remoteInterface);
}

otherwise what's the point of passing remoteInterface?

Even finer request / response logging

While sent requests and responses are logged already (given the correct java.util.logging configuration), sent and received HTTP headers are not logged. This is useful for debugging purposes.

Document how to use with Spring Boot

I'm trying to use jsonrpc4j with Spring Boot and having some trouble. I'm still debugging, but it would be great if the README would have a section on correct usage with Spring Boot.

JSON-RPC GET handling has an extra URL decode on params

When the params for a JSON-RPC request are URL encoded, the are Base64 encoded, and the URL encoded to make the Base64 URL safe (see http://jsonrpc.org/historical/json-rpc-over-http.html#encoded-parameters). In JsonRpcServer.createInputStream, the params argument has already been URL decoded, and then it is converted from Base64 to a String, however, that string is then URL decoded again. This causes any URL unsafe characters in the params to be changed, corrupting the params.

Use error stream in JsonRpcHttpClient when status code is not 200

I ran into problems using this fine library with the bitcoind service. It turns out that it always returns 500s when the input is somehow malformed but also gives an explanation as JSON response. Unfortunately, Java's HTTPUrlConnection just throws an exception without the data when trying to open the input stream. In this case, jsonrpc4j should use the error stream and try to parse that, as suggested here: http://stackoverflow.com/questions/9129766/urlconnection-is-not-allowing-me-to-access-data-on-http-errors-404-500-etc

Expose Request and Response objects to JSONRPC methods

Hi :)

I'm interested in learning how/why not the Request and Response objects can be passed over from Servlet classes to Service/ServiceImpl methods. There are two unholy reasons for why I want this:

  1. I like storing logged-in-User-IDs in HttpSession object and I've so far found no elegant way to pass any server-side objects to the JSONRPC methods. Without them I have no way of verifying if the User is legit, has the right access level to use the method etc.

  2. I like dynamically updating page components by making JavaScript calls for JSP content as strings, followed by $(selector).html(content). Without the response object present in a JSONRPC method I can't include the JSPs.

I've already solved both of the above by hacking together a static object that pushes/gets/clears the Request and Response objects to a Thread-keyed Map but it felt so wrong that I have trouble sleeping at night.

My question therefore is: Can I/Would it be inherently BAD to expose the Request/Response objects to the JSONRPC methods through some proper channel?

JsonMappingException on server when client closes connection

What steps will reproduce the problem?

  1. Create StreamServer, JsonRpcClient
  2. Make a call, then close client connection

What is the expected output? What do you see instead?
Server's log:

SEVERE: Exception while handling request
com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
at [Source: com.googlecode.jsonrpc4j.NoCloseInputStream@3e0ebb; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:163)
at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:2620)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2562)
at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:1500)
at com.googlecode.jsonrpc4j.JsonRpcServer.handle(JsonRpcServer.java:224)
at com.googlecode.jsonrpc4j.StreamServer$Server.run(StreamServer.java:214)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)

What version of the product are you using? On what operating system?
Ubuntu 12.10, jsonrpc4j 0.28

Please provide any additional information below.
There is a test case in attached file

http://code.google.com/p/jsonrpc4j/issues/detail?id=58

Access to HttpUrlConnection in JsonRpcHttpClient

The underlying HttpUrlConnection in JsonRpcHttpClient is pretty much hidden, e.g. there is no way to access response headers nor can its implementation easily be changed (prepareConnection can be overridden, but it not only opens a connection, but also sets a bunch of properties on this connection already).

No support for authorization tokens

Propose a patch to JsonRpcClient.java that allows for a simple method to insert authentication tokens when supported/required by json-rpc 2.0. Proposed patch is below:

--- java/jsonrpc4j/src/main/java/com/googlecode/jsonrpc4j/JsonRpcClient.java    2014-04-16 09:26:42.000000000 -0400
+++ Workspace/jsonrpc4j/src/com/googlecode/jsonrpc4j/JsonRpcClient.java 2014-04-17 16:00:17.000000000 -0400
@@ -31,6 +31,16 @@
    private Random random;
    private RequestListener requestListener;
    private ExceptionResolver exceptionResolver = DefaultExceptionResolver.INSTANCE;
+   private String authToken;
+   
+   /**
+    * Need a way to pass on json-rpc auth tokens
+    * Added by JGC: BlackMesh, Inc.
+    * @param authToken
+    */
+   public void setAuthToken(String authToken) {
+       this.authToken = authToken;
+   }

    /**
     * Creates a client that uses the given {@link ObjectMapper} to
@@ -402,6 +412,10 @@
            request.put("params", mapper.valueToTree(arguments));
        }

+       if (authToken != null) {
+           request.put("auth", authToken);
+       }
+       
        // show to listener
        if (this.requestListener!=null) {
            this.requestListener.onBeforeRequestSent(this, request);

Feature Request: Add ability to specify custom ExceptionResolver when using AutoJsonRpcClientProxyCreator

Right now there is no way to specify custom ExceptionResolver implementation when using AutoJsonRpcClientProxyCreator: a JsonProxyFactoryBean class is used to create a proxy and it creates an instance of JsonRpcHttpClient with DefaultExceptionResolver implementation attached.

It would be great to have a property in AutoJsonRpcClientProxyCreator to specify ExceptionResolver via xml config. Or the other way is to add a property in @JsonRpcService annotation.

http://code.google.com/p/jsonrpc4j/issues/detail?id=57

1.2 release

Is there any planned date for 1.2 release?
Also in commit dcddedf, version was changed from 1.2-SNAPSHOT to 1.2.1-SNAPSHOT, so it is not clear if 1.2/1.2.0 was supposed to be released.

Thanks

Support JAXB/Jackson Objects in Request Param

I have Request/Response JaxB POJOs. I want to use them in such a way that the params in JSONRPC request use the field names in my POJOs. But, right now, it is not supported. So, I have to annotate my single Request Param with a param name.

Desired
{"jsonrpc": "2.0", "method": "someMethod", "params": {"paramA": 23, "paramB": 42}, "id": 3}

Right now, the request is as follows
{"jsonrpc": "2.0", "method": "someMethod", "params": {"input": {"paramA": 23, "paramB": 42}}, "id": 3}

May I request to support this feature?

Unable to use JSONRPC4j Client with JSON-RPC Server running with 1.0 version

Using JSONRPC4j library - Streaming Server feature.

I wrote a simple class which uses JsonRpc4j-JsonRpcClient and communicates with JSON-RPC Server 1.0 Version and server throws a version compatibility exception.

How to use JSON-RPC4j library for JSON-RPC1.0 Servers?

It looks like JSON-RPC4j library works only for JSON-RPC2.0 Server.

Please let me know.

Add copyright notice to all source files

What steps will reproduce the problem?

  • Attempt to get legal dept. to approve use of jsonrpc4j in a commercial project. :)

What is the expected output? What do you see instead?

  • Expected output is approval by legal dept. Instead, legal dept. has denied approval due to no copyright & permission notice included in the source.

What version of the product are you using? On what operating system?

  • All versions/OS.

Please provide any additional information below.
I like the approach of the project, it makes jsonrpc exceedingly easy to implement. However my legal dept. is advising that without a copyright & permission embedded in the source I will have to remove it from my project. The MIT license has the following clause "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software." which is not currently being fulfilled so they will not allow me to ship with it. Would you be willing to amend the source files accordingly? I have included the MIT license text below.

Thanks,
Tom

Copyright (c)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

http://code.google.com/p/jsonrpc4j/issues/detail?id=66

Its not immediately clear to me how to use the client with a 3rd party service ?

The code snippets is here ?

JsonRpcHttpClient client = new JsonRpcHttpClient(
new URL("http://example.com/UserService.json"));

User user = client.invoke("createUser", new Object[] { "bob", "the builder" }, User.class);

OK so ...
It would be nice if you could give us a few more hints of how to use the client with an external service ?

For example do I create an interface for the expected result for the method call and pass that class to the invoker ?

Or do I create a requestListener object and pass that to the setRequestListener method ? Then handle the response there ?

How an would HTTP error be caught and handled if the invoker returns only a class instance we defined ourselves ?

Then how do I do authentication with the server in the first place ?

just a couple of simple code snippets to send me in the right direction would sure help

Thanks

Include OSGi metadata in the manifest for 1.2 release

#11 added OSGi metadata in the manifest before 1.1 release.

But #13 moved the maven configuration in a new profile.

As a result 1.1 was released without any OSGi metadata in the manifest.

Any idea why this was moved to a profile?
Can we fix this for 1.2?

I can help, but for that I first need to know what command is run to generate a release version. Any place where this is documented? Can I just remove the shaded-bundle profile and provide just OSGi manifest generation?

Thanks

Use getProxyForService() instead of getService() in AbstractJsonServiceExporter

Hi,

in order to allow interceptors and other AOP on the RemoteExporter please use getProxyForService() instead of getService() when building JsonRpcServer (see AbstractJsonServiceExporter:[email protected]).

Thanx a lot for writing this code!

For example:

<bean name="/LobbyService.json" class="com.googlecode.jsonrpc4j.spring.JsonServiceExporter">
    <property name="service" ref="lobbyService" />
    <property name="serviceInterface" value="org.example.net.LobbyService" />
    <property name="interceptors" ref="performanceStatsMethodInterceptor" />
</bean>

http://code.google.com/p/jsonrpc4j/issues/detail?id=59

"No content to map due to end-of-input" exception while reading message from InputStream...

Hi,

While reading JSON-RPC message by using JsonRpcClient::readResponse() API, sometimes it throws the following exception:


Caused by: com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
at [Source: com.googlecode.jsonrpc4j.NoCloseInputStream@52853dcb; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:2836)

at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapp...

Why this exception occurs?

How to handle this exception?

Do I need to reset the connection when this exception occurs?

Please let me know.

Thanks,
Sudheer

Separating invoke() and readResponse() calls

Hi,

First, Thanks for this project. I find it very useful.

I'm using the JsonRpcClient class to work against a socket.
When I couple each invoke() call with readResponse() call immediately afterwards, everything works fine.

However, if I chain multiple invoke() calls and only then call readResponse(), the first read returns with a response, but it cleans the socket from all other responses, and the following readResponse() call were blocked.

I searched for the source of the problem, and it seems to originate from the jackson library you use. The problem is described in http://jackson-users.ning.com/forum/topics/reading-multiple-objects-from

In the above link there are also some solutions to it. Can they be applied to the JsonRpcClient somehow?

Thanks,
Arye

testcase error when build jsonrpc4j 1.0

the jdk version is 1.5
but the artifacts of dependency compiled by 1.7.so i got the error when run the testcase:Unsupported major.minor version 51.0

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1-b01</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>9.0.0.RC0</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <artifactId>javax.servlet</artifactId>
                    <groupId>org.eclipse.jetty.orbit</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>9.0.0.RC0</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <artifactId>javax.servlet</artifactId>
                    <groupId>org.eclipse.jetty.orbit</groupId>
                </exclusion>
            </exclusions>
        </dependency>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.