Я создаю приложение, которое будет работать на Jetty Server. Мой основной класс расширен от ResourceConfig, чтобы запустить параметр инициализации "javax.ws.rs.Application" для этого класса. Я также использовал ServiceLocator для возврата экземпляров службы по требованию;также использовал AbstractBinder для связывания класса с областью Singleton & Immediate.
Мой код класса ResourceConfig, связанный с внедрением зависимостей, выглядит следующим образом:
public class MyServer extends ResourceConfig {
@Inject
public MyServer() {
packages("My.REST");
}
public static void main(String[] args) {
final Server server = new Server(MythreadPool);
HttpConfiguration httpConfig = new HttpConfiguration();
httpConfig.addCustomizer(new ForwardedRequestCustomizer());
ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory(httpConfig));
//Code for connector porperties
server.addConnector(connector);
ContextHandlerCollection contexts = new ContextHandlerCollection();
server.setHandler(contexts);
final WebAppContext webApp = setupWebAppContext(contexts, conf);
ServiceLocator serviceLocator = ServiceLocatorFactory.getInstance().create("my-locator");
ServiceLocatorUtilities.enableImmediateScope(serviceLocator);
ServiceLocatorUtilities.bind(
sharedServiceLocator,
new AbstractBinder() {
@Override
protected void configure() {
bind(ClassA.class).to(InterfaceService.class).in(Immediate.class);
}
});
}
webApp.addEventListener(
new ServletContextListener() {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
servletContextEvent
.getServletContext()
.setAttribute(ServletProperties.SERVICE_LOCATOR, serviceLocator);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {}
});
setupRestApiContextHandler(webApp, conf);
try {
server.start();
} catch (Exception e) {
LOG.error("Error while running jettyServer", e);
System.exit(-1);
}
}
private static WebAppContext setupWebAppContext(ContextHandlerCollection contexts, Configuration conf) {
WebAppContext webApp = new WebAppContext();
webApp.setContextPath(conf.getServerContextPath());
webApp.addServlet(new ServletHolder(new DefaultServlet()), "/*");
contexts.addHandler(webApp);
webApp.addFilter(new FilterHolder(MyFilter.class), "/*", EnumSet.allOf(DispatcherType.class));
webApp.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed","true");
return webApp;
}
private static void setupRestApiContextHandler(WebAppContext webapp, Configuration conf) {
final ServletHolder servletHolder =
new ServletHolder(new org.glassfish.jersey.servlet.ServletContainer());
servletHolder.setInitParameter("javax.ws.rs.Application", MyServer.class.getName());
servletHolder.setName("rest");
servletHolder.setForcedPath("rest");
webapp.setSessionHandler(new SessionHandler());
webapp.addServlet(servletHolder, "/api/*");
webapp.setInitParameter("shiroConfigLocations", "ShiroFilePathURI");
webapp
.addFilter(ShiroFilter.class, "/MyRestApiPath/*", EnumSet.allOf(DispatcherType.class))
.setInitParameter("staticSecurityManagerEnabled", "true");
webapp.addEventListener(new EnvironmentLoaderListener());
}
}
Мой ClassA выглядит следующим образом:
public class ClassA implements InterfaceService {
@Inject
public ClassA(SomeClass instances){
//initialize some variable
}
}
Существует класс REST, в который вводится InterfaceService:
@Path("/my_rest")
@Produces("application/json")
@Singleton
public class RestApi {
private InterfaceService interfaceService;
@Inject
public RestApi(InterfaceService interfaceService) {
this.interfaceService = interfaceService;
}
}
Когда я запускаю этот код, я получаю следующее исключение:
"javax.servlet.ServletException: MultiException имеет 4 исключения: 1. java.lang.IllegalStateException: не удалось найти активный контекст для org.glassfish.hk2.api.Immediate 2. java.lang.IllegalStateException: при попытке создать службудля SystemDescriptor (реализация = контракты ClassA = {InterfaceService} "
В классе MyServer, когда я связываю класс с областью действия Singleton, он работает, как и ожидалось. То есть bind(ClassA.class).to(InterfaceService.class).in(Singleton.class);
Тогда, если я обновлю свой класс RestApi ниже
@Path("/my_rest")
@Produces("application/json")
@Singleton
public class RestApi {
private ClassA classA;
@Inject
public RestApi(ClassA classA) {
this.classA = classA;
}
}
Тогда все будет работать, как и ожидалось, с немедленной областью действияа также.
Для меня требуется изменение области действия на Немедленное, так как мне нужно выполнить определенные операции в классе при запуске сервера. Кроме того, я не могу использовать ссылку на ClassA
в RestApi, поскольку в будущем появятся другие реализации интерфейса InterfaceService
, поэтому мне нужно кодировать интерфейс в RestApi
. Любая подсказка о том, что мне нужно сделать, чтобы заставить код работать с немедленной областью действия, привязав его к InterfaceService