Hi
On 19/01/15 11:15, Maarten Boekhold wrote:
Hi,
I already have an /existing instance/ of "TheResource" ("resource") that
I /must/ use to handle my incoming REST requests. This "resource" object
has received a large amount of very complex initialization which I don't
see how it can be handled through the CXF lifecycle management (eg
SingletonResourceProvider or PerRequestResourceProvider). Also, we
don't, can't and won't use Spring... not my choice.
The code below is just a test case, and the real program is many times
more complex. Just pointing that out, in case you think I'm doing
something way to complex for the scenario I'm showing here.
I'm still curious if implementing this through overriding
configureSingleton() would be simpler, except that I have no idea what
I'd need to put in that method, as I don't actually see
configureSingleton() used anywhere in the current CXF source code...
That method is there for custom servlets to have a singleton instance
initialized if the default initialization support is not sufficient
hence it is not used in the code base. So one option is to let the
servlet create an instance and cast it to your Resource class in
configureSingleton and continue with the initialization.
Another option is not to use CXFNonSpringJaxrsServlet at all. Do
JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean();
bean.setAddress(myAddress);
bean.setServiceBean(myBean);
bean.create();
This will create an embedded Jetty instance with the endpoint available
at 'myAddress'.
This is exactly what the servlet does internally.
If you do need to work directly with Jetty handlers than the override
option would be the simplest one.
The other option is to do
new CXFNonSpringJaxrsServlet() {
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean();
bean.setAddress(myAddress);
bean.setServiceBean(myBean);
bean.create();
}
}
As I said, I'll add
CXFNonSpringJaxrsServlet(Application) constructor, to make it simpler.
Cheers, Sergey
Maarten
On 2015-01-19 13:55, Sergey Beryozkin wrote:
Hi
I don't understand what are you trying to do. It does look too complex.
What exactly are you trying to achieve besides registering a CXF
servlet as a Jetty handler ?
What do you need to initialize, the service implementation, the
providers, both ?
Sergey
On 19/01/15 07:24, Maarten Boekhold wrote:
Hi again,
Studied the CXF source code a bit more, and I've got something that
works, by overriding getResourceProviders() and providing my own
ResourceProvider implementation as follows. Bit complex however, I would
not mind some simpler standard API around this!
public class TheApp {
private static final Logger LOG =
LoggerFactory.getLogger(TheApp.class);
TheResource resource;
public static class BeanResourceProvider implements
ResourceProvider {
private final Object theBean;
public BeanResourceProvider(Object theBean) {
this.theBean = theBean;
}
@Override
public Object getInstance(Message m) {
return theBean;
}
@Override
public void releaseInstance(Message m, Object o) {
}
@Override
public Class<?> getResourceClass() {
return theBean.getClass();
}
@Override
public boolean isSingleton() {
return true;
}
};
public TheApp(int port) throws Exception {
resource = new TheResource();
CXFNonSpringJaxrsServlet context = new CXFNonSpringJaxrsServlet() {
public void configureSingleton(Object o) {
LOG.info("configureSingleton() called");
}
public Map<Class<?>, ResourceProvider>
getResourceProviders(ServletConfig servletConfig,
Map<Class<?>, Map<String, List<String>>> resourceClasses) throws
ServletException {
LOG.info("getResourceProviders called");
Map<Class<?>, ResourceProvider> map = new HashMap<Class<?>,
ResourceProvider>();
for (Map.Entry<Class<?>, Map<String, List<String>>> entry :
resourceClasses.entrySet()) {
Class<?> c = entry.getKey();
LOG.info("getting provider for {}", c.getName());
map.put(c, new BeanResourceProvider(resource));
}
return map;
}
};
ServletHolder holder = new ServletHolder(context);
holder.setInitParameter("jaxrs.serviceClasses",
"com.misys.tools.integration.cxfjetty.TheResource");
ServletContextHandler handler = new ServletContextHandler();
handler.addServlet(holder, "/*");
handler.setContextPath("/theroot");
Server server = new Server(port);
server.setHandler(handler);
server.start();
server.join();
}
public static void main(String[] args) throws Exception {
TheApp app = new TheApp(8122);
}
}
Maarten
On 2015-01-19 11:07, Maarten Boekhold wrote:
Hi,
I've managed to override configureSingleton(), but at the moment my
implementation just logs something and then delegates to
super.configureSingleton() (which is empty itself btw). I'm not
exactly sure what code I would need to include in my implementation.
Any suggestions?
Another suggestions I got on Stack Overflow was to extend
CXFNonSpringJaxrsServlet.getResourceProviders(). Same thing here, I
can't figure out what my implementation would need to do :).
Does anybody have any further pointers/suggestions? Btw. Haven't
figured out how/where to register a custom application yet, so no
progress in that direction yet.
Maarten
On 2015-01-18 21:27, Sergey Beryozkin wrote:
Hi
Right now it is not possible to pass an initialized instance directly
to the servlet, though I can see it can be handy in some cases.
In many cases one can still achieve the same with the current
approach, example, you can have Catalog properties passed too,
Catalog(a=1 b=2), see the example at the wiki. List properties can be
passed too.
if you do need to pass some ready instance then you can either go
with working directlu with JAXRSServerFactoryBean (I'd prefer it
instead of dealing directly with Jetty handlers), use jaxrs:server
with an absolute HTTP address, or in this case, extend
CxfNonSpringJaxrsServlet and override its configureSingleton class or
it it is more involved, register a custom Application.
I'll add a constructor CxfNonSpringJaxrsServlet(Application) to make
things simpler too
Cheers, Sergey