Проблема передачи атрибутов контекста в 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 ответа:
Из вашего обновленного раздела удалите 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; }; };
Вы можете найти полный исходный код изздесь .
Ссылка На Ресурс:
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() ... }