Been working on this one for hours and nothing seems to work. It's Jersey 2.23.2. The idea is that I want to inject a request based Hibernate Session into a Jersey provider to use in my REST API. Instead, I get this:
javax.servlet.ServletException: A MultiException has 2 exceptions. They are:
1. java.lang.IllegalStateException: Could not find an active context for javax.enterprise.context.RequestScoped
2. java.lang.IllegalStateException: While attempting to create a service for SystemDescriptor(
implementation=com.pixmoto.api.server.SFFactory
contracts={org.hibernate.Session}
scope=javax.enterprise.context.RequestScoped
qualifiers={}
descriptorType=PROVIDE_METHOD
descriptorVisibility=NORMAL
metadata=
rank=0
loader=org.glassfish.hk2.utilities.binding.AbstractBinder$2@6e9becd5
proxiable=null
proxyForSameScope=null
analysisName=null
id=129
locatorId=0
identityHashCode=1082491454
reified=true) in scope javax.enterprise.context.RequestScoped an error occured while locating the context
Here's my code:
public class JerseyResourceConfig extends ResourceConfig {
public JerseyResourceConfig() {
packages(this.getClass().getPackage().getName() + ";org.codehaus.jackson.jaxrs");
register(new AbstractBinder(){
@Override
protected void configure() {
bindFactory(SFFactory.class)
.to(Session.class)
.in(RequestScoped.class);
}
});
}
}
public class App {
private static final Logger logger = LogManager.getLogger(App.class);
public static void main(String[] args) throws Exception {
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
Server jettyServer = new Server(8080);
Slf4jRequestLog requestLog = new Slf4jRequestLog();
requestLog.start();
jettyServer.setRequestLog(requestLog);
ClassList classlist = ClassList.setServerDefault(jettyServer);
classlist.addAfter(
"org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.plus.webapp.EnvConfiguration",
"org.eclipse.jetty.plus.webapp.PlusConfiguration");
jettyServer.setHandler(context);
JerseyResourceConfig config = new JerseyResourceConfig();
ServletHolder servlet = new ServletHolder(new ServletContainer(config));
context.addServlet(servlet, "/*");
try {
jettyServer.start();
jettyServer.join();
} catch (Exception ex) {
logger.error(ex);
throw ex;
} finally {
jettyServer.destroy();
}
}
}
@Path("/api/users")
@Produces(MediaType.APPLICATION_JSON)
public class UserProvider {
@Inject
private javax.inject.Provider<Session> session;
@GET
public List<User> getUsers() {
Session s = session.get();
List<User> users = s.createQuery( "from User", User.class).getResultList();
return users;
}
}
public class SFFactory implements Factory<Session> {
private final SessionFactory sessionFactory;
public SFFactory() {
this.sessionFactory = new Configuration()
.configure() // configures settings from hibernate.cfg.xml
.buildSessionFactory();
}
@Override
public Session provide() {
return sessionFactory.openSession();
}
@Override
public void dispose(Session session) {
if (session.isOpen()) {
session.close();
}
}
}
I've tried what seems like hundreds of permutations. Tirelessly searched the web. As long as I have spent looking at this with no resolution, I'm figuring it must be something really simple.
I can get it to bind when I specify Singleton rather than RequestScoped in the AbstractBinder configure method, but that is not what I would like. I would like a new Session on every request for a single SessionFactory.
I don't have any more hair to pull out. Any help would be immensely appreciated.
You're using the wrong RequestScoped
(you're using the CDI one). You should be using the Jersey specific one.