Проблема передачи атрибутов контекста в ServerResource


Мое приложение пытается установить атрибуты контекста:

    final Router router = new Router();
    router.attachDefault(HttpListener.class);

    org.restlet.Application myApp = new org.restlet.Application() {
        @Override
        public org.restlet.Restlet createInboundRoot() {
            getContext().getAttributes().put("mysharedobj", new MySharedObj());
            return router;
        };
    };
    Component component = new Component();
    component.getDefaultHost().attach("/", myApp);

    new Server(Protocol.HTTP, port, component).start();

В моем HttpListener я утверждаю, что контекст не является нулевым:

public class HttpListener extends ServerResource {

    public MySharedObj mysharedobj;

    public HttpListener() { }  

    @java.lang.Override
    public void init(Context context, Request request, Response response) {

        assert context != null;  // throws java.lang.AssertionError

        // my end goal is to pass a shared object to my listener
        mysharedobj = context.getAttributes().get("mysharedobj");
    }
    ...
}

Однако, java.яз..AssertionError выбрасывается, потому что контекст равен null. Моя конечная цель-передать общий объект моему слушателю. Есть ли другой способ сделать это?

Где я ошибаюсь? Примечание: Я использую Restlet 2.1.7. Мое приложение всегда запускается из приложения android, поэтому контекст сервера не является доступный.


Обновление:

Я также попытался использовать контекст приложения:

    final Router router = new Router();
    router.attachDefault(HttpListener.class);

    Component component = new Component();

    final Context ctx = component.getApplication().getContext().createChildContext();
    ctx.getAttributes().put("mysharedobj", new MySharedObj());

    org.restlet.Application myApp = new org.restlet.Application(ctx) {
        @Override
        public org.restlet.Restlet createInboundRoot() {
            return router;
        };
    };

И..

public HttpListener() {
    Context ctx = getApplication().getContext();
    assert ctx.getAttributes().size() > 0;  // Throws AssertionError
    ...     
}

В этом подходе я могу получить доступ к контексту приложения, но атрибуты по какой-то причине не задаются.

2 6

2 ответа:

Из вашего обновленного раздела удалите final, тогда он будет работать. Потому что вы можете задать конечную переменную только в constructor или в an initializer. В обычных методах нельзя изменить значение переменных, которое объявлено final.

Итак, ваш код будет

 Router router = new Router(); // Remove final from this.
    router.attachDefault(HttpListener.class);

    Component component = new Component();

    Context ctx = component.getApplication().getContext().createChildContext(); // Remove final
    ctx.getAttributes().put("mysharedobj", new MySharedObj());

    org.restlet.Application myApp = new org.restlet.Application(ctx) {
        @Override
        public org.restlet.Restlet createInboundRoot() {
            return router;
        };
    };

Вы можете найти полный исходный код изздесь .

Ссылка На Ресурс:

  1. Restlet Framework-Hello World Пример
  2. Restlet Авторизация

UPDATE1:

Из документации Restlet и примера кода я получил несколько полезных областей. Надеюсь, это поможет вам.

public class MyApiWithRoleAuthorization extends Application {
    @Override
    public Restlet createInboundRoot() {
        Router router = createRouter();
        return router;
    }
    private Router createRouter() {
        //Attach Server Resources to given URL
        Router router = new Router(getContext());
        router.attach("/resource1/", Resource1.class);
        router.attach("/resource2/", Resource2.class);
        return router;
    }
      public static void main(String[] args) throws Exception {
        //Attach application to http://localhost:9000/v1
        Component c = new Component();
        c.getServers().add(Protocol.HTTP, 9000);
        c.getDefaultHost().attach("/v1", new MyApiWithRoleAuthorization());
        c.start();
    }
}

Классы ресурсов, назовем их Resource1, Resource2 и т. д... и скопируйте-вставьте их содержимое отсюда:

Resource0.java

public class Resource0 extends ServerResource{

    @Get
    public String represent() throws Exception {
        return this.getClass().getSimpleName() + " found !";
    }

    @Post
    public String add() {
        return this.getClass().getSimpleName() + " posted !";
    }

    @Put
    public String change() {
        return this.getClass().getSimpleName() + " changed !";
    }

    @Patch
    public String partiallyChange() {
        return this.getClass().getSimpleName() + " partially changed !";
    }

    @Delete
    public String destroy() {
        return this.getClass().getSimpleName() + " deleted!";
    }
}

Лучшее решение, которое у меня есть на данный момент, - это использовать синглетный java-класс с фабричным методом для создания моего объекта и синглетным геттером для извлечения этого объекта, например

final Router router = new Router();
router.attachDefault(HttpListener.class);

MySharedObj myobj = MySharedObj.newInstance();

org.restlet.Application myApp = new org.restlet.Application() {
    @Override
    public org.restlet.Restlet createInboundRoot() {
        return router;
    };
};
Component component = new Component();
component.getDefaultHost().attach("/", myApp);

new Server(Protocol.HTTP, port, component).start();

// in a different thread
MySharedObj myobj = MySharedObj.get();
myobj.doStuff()

И внутри моего HttpListner:

public HttpListener() {
    MySharedObj myobj = MySharedObj.get();
    myobj.doStuff()       
    ...     
}