Android上的Restlet服务器:客户端获取空对象 [英] Restlet server on Android: client is getting a null object

查看:152
本文介绍了Android上的Restlet服务器:客户端获取空对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实现了一个简单的Android Restlet服务器演示,可以将传感器值提供给Restlet客户端. 但是,当restlet客户端接收到该对象时,该对象为null.我想不会有太多丢失,因为该事务表明它已在服务器logcat中正确完成:

I implemented a simple Android Restlet server demo that can provide the sensor values to a Restlet client. However, when the restlet client receives the object, it is null. I suppose there is not much missing because the transaction shows that it was done correctly in the server logcat:

D/SensorTemperature: GET temperature: 20.0
W/System.err: 2015-10-23    20:28:37    192.168.2.129   -   -   8080    GET /sensors/temperature    -   200 -   0   198 http://192.168.2.94:8080    Restlet-Framework/2.3.5 -

在客户端,ClientResource打印(logcat):

And on the client side, the ClientResource prints (logcat):

ClientProxy for resource: GET http://192.168.2.94:8080/sensors/temperature HTTP/1.1 => HTTP/1.1 - OK (200) - The request has succeeded

此外,使用restlet请求/响应时,浏览器界面可以按预期工作(请参见下面的"/test":).

Moreover, the browser interface works as expected when using the restlet request/response (see "/test" below: ).

我遵循了Restrest官方教程: http://restlet.com/technical -resources/restlet-framework/guide/2.2/introduction/first-steps/first-application

I followed the official Restlet tutorial: http://restlet.com/technical-resources/restlet-framework/guide/2.2/introduction/first-steps/first-application

git: https://github.com/restlet/restlet-tutorial/tree/master/modules/org.restlet.tutorial.webapi/src/main/java/org/restlet/tutorial

与此示例一起: http://maxrohde.com/2011/09/02/restlet-quickstart/

代码:

这是restlet服务器:

Here is the restlet server:

public class ServerFactory {

    static {
        // Get NIO engines, instead of defaults
        Engine.getInstance().getRegisteredServers().add(new HttpsServerHelper(null));
        Engine.getInstance().getRegisteredServers().add(new HttpServerHelper(null));
        // Engine.setLogLevel(Level.FINEST);
        Engine.getInstance().getRegisteredConverters().add(new JacksonConverter());
    }

    private static Restlet restlet = new Restlet() {
        @Override
        public void handle(Request request, Response response) {
            Date date = new Date();
            float temp = WSDataProvider.getInstance().getTemperature();
            response.setEntity("Hello World!\nTime: " + date + "\nTemp: " + temp, MediaType.TEXT_PLAIN);
        }
    };

    public static Server createServer(int port, final String rootUri) {
        Component component = new Component();

        Server server = component.getServers().add(Protocol.HTTP, port);

        // Attach the sample application.
        component.getDefaultHost().attach("/test", restlet);

        SensorsApplication sensorsApp = new SensorsApplication();
        component.getDefaultHost().attach("/sensors", sensorsApp);

        return server;  // server.start() and server.stop() called via Android buttons
    }
}

和客户:

Thread thread = new Thread(new Runnable(){
    @Override
    public void run() {
        try {
            Engine.getInstance().getRegisteredConverters().add(new JacksonConverter());

            // Initialize the resource proxy.
            final ClientResource cr = new ClientResource("http://192.168.2.94:8080/sensors/temperature");
            final SensorResource resource = cr.wrap(SensorResource.class);

            // Get the remote temperature sensor
            final SensorBase sensorBase = resource.retrieve();
            if (sensorBase != null)
                Log.e(TAG, "sensorBase.getData() = " + sensorBase.data);
            else
                Log.e(TAG, "sensorBase is null !!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});

thread.start();

SensorBase类:(客户端+服务器)

SensorBase class: (client + server)

public class SensorBase implements Serializable {

    private static final long serialVersionUID = 1L;

    public static final int TYPE_UNKNOWN = 0;
    public static final int TYPE_TEMPERATURE = 1;
    public static final int TYPE_HUMIDITY = 2;

    public int type;
    public float data;

    public SensorBase(final int type) {
        super();
        this.type = type;
    }
}

SensorResource类:(客户端+服务器)

SensorResource class: (client + server)

public interface SensorResource {
    @Get
    public SensorBase retrieve();
}

SensorTemperature类:

SensorTemperature class:

public class SensorTemperature extends ServerResource implements SensorResource {

    private static final String TAG = "SensorTemperature";
    private static volatile SensorBase sensorBase = new SensorBase(SensorBase.TYPE_TEMPERATURE);

    public SensorBase retrieve() {
        float temp = WSDataProvider.getInstance().getTemperature();
        Log.d(TAG, "GET temperature: " + temp);
        sensorBase.data = temp;
        return sensorBase;
    }
}

SensorsApplication类:

SensorsApplication class:

public class SensorsApplication extends Application {
    public Restlet createInboundRoot() {
        Router router = new Router(getContext());
        router.attach("/temperature", SensorTemperature.class);
        //TODO add more sensors
        return router;
    }
}

更新

我通过包含杰克逊jar文件com.fasterxml.jackson.core.jar修复了空指针异常.仅在Restlet客户端使用Engine.setLogLevel(Level.FINEST);

I have fixed the null pointer exception by including the jackson jar file com.fasterxml.jackson.core.jar. The class not found error was only shown when the Restlet client was using Engine.setLogLevel(Level.FINEST); !

但是,我现在从客户端收到以下异常:

However, I get the following Exception from the client now:

org.restlet.resource.ResourceException: Unprocessable Entity (422) - The server understands the content type of the request entity and the syntax of the request entity is correct but was unable to process the contained instructions

谢谢!

推荐答案

实际上,这不是Restlet的问题,而是Jackson的问题.如果您查看422错误的根本原因,则会看到以下内容:

In fact, it's not a problem from Restlet but from Jackson. If you have a look at the root cause of the 422 error, you'll see this:

Caused by: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class SensorBase]: can not instantiate from JSON object (need to add/enable type information?)
 at [Source: sun.nio.ch.ChannelInputStream@1eb0d79; line: 1, column: 2]
 at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
 at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1071)
 at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:264)
 at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:124)
 at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1269)
 at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:864)
 at org.restlet.ext.jackson.JacksonRepresentation.getObject(JacksonRepresentation.java:299)
 at org.restlet.ext.jackson.JacksonConverter.toObject(JacksonConverter.java:208)
 at org.restlet.service.ConverterService.toObject(ConverterService.java:229)
 at org.restlet.resource.Resource.toObject(Resource.java:889)
 ... 3 more

Jackson对对象SensorBase进行反序列化需要在此类中使用空的构造函数:

The deserialization of your object SensorBase by Jackson requires an empty constructor in this class:

public class SensorBase implements Serializable {
    private static final long serialVersionUID = 1L;

    public static final int TYPE_UNKNOWN = 0;
    public static final int TYPE_TEMPERATURE = 1;
    public static final int TYPE_HUMIDITY = 2;

    public int type;
    public float data;

    public SensorBase() {

    }

    public SensorBase(final int type) {
        super();
        this.type = type;
    }

    (...)
}

希望它对您有帮助, 蒂埃里

Hope it helps you, Thierry

这篇关于Android上的Restlet服务器:客户端获取空对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆