android - Android 上的 ReSTLet 服务器 : client is getting a null object

标签 android restlet restlet-2.0

我实现了一个简单的 Android ReSTLet 服务器演示,它可以向 ReSTLet 客户端提供传感器值。 然而,当 reSTLet 客户端收到该对象时,它是空的。我想没有太多遗漏,因为事务显示它在服务器 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):

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”:)。

我遵循了官方的 ReSTLet 教程: 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服务器:

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类:(客户端+服务器)

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;
    }
}

传感器资源类:(客户端+服务器)

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

传感器温度类:

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;
    }
}

传感器应用类:

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

更新

我通过包含 jackson jar 文件 com.fasterxml.jackson.core.jar 修复了空指针异常。类未找到错误仅在 ReSTLet 客户端使用 Engine.setLogLevel(Level.FINEST); 时显示!

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

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 错误的根本原因,您会看到:

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 的反序列化需要此类中的空构造函数:

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;
    }

    (...)
}

希望对你有帮助, 蒂埃里

关于android - Android 上的 ReSTLet 服务器 : client is getting a null object,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33311268/

相关文章:

java - ReSTLet 客户端卡住 HTTPS 请求

Android 在 iframe 中嵌入视频未根据 webview 高度变化调整大小

java - Camel ReSTLet maxThreads 未按预期工作

android - 我应该使用哪个框架在 Android 上运行 OData API?

java - ReSTLet-1.1 example\book\rest\ch2\Example2_5 没有用于 HTTPS 的客户端连接器

java - ReSTLet 流数据

java - 使用 ReSTLet 设置自定义内容范围 header

java - 尝试访问自定义 AlertDialog 的子级会导致 NullPointerException

android - 尝试转到新的Intent时,Android App崩溃

java - UsbDevice requestPermission 被拒绝,且未显示请求对话框提示