Hi,
Thanks for sharing these results, let me comment, please see below
On 20/08/14 07:13, jordan wrote:
Hi dear all,
We would like to use JAXRS-2.0 and CXF in our project.
And we would like use some @Context injection in our test.
But I found the Configuration and Singleton Constructor @Context
injection
don't work. I also searched cxf and test project, but didn't find any
related test and usage.
I'm not sure do you have any related test or work, and could your please
give some suggestion?
Appreciate it! :)
*1, Configuration injection doesn't work in both Resource and Filter:*
Right, see
https://issues.apache.org/jira/browse/CXF-5899
I've never been sure how would the application class would use it, but,
I guess I can imagine how a filter would use, especially a client filter
may be (check the properties, etc). It's supported all right directly in
the Client API, but not on the server side. The preliminary TCK
available to Apache did not have any issues with it so it kind of fell
of my radar, supporting the actual injection. Several people have
pointed out to it. Time to get it fixed :-)
Here is one my test resource:
private UriInfo uriInfo1;
@Context
private UriInfo uriInfo2;
private Configuration config1;
@Context
private Configuration config2;
@Context
public void setUriInfo(UriInfo ui) {
uriInfo1 = ui;
}
@Context
public void setConfiguration (Configuration co) {
config1= co;
}
@GET
@Path("/" + ContextUtil.URIINFONAME1)
@Produces("text/plain")
public String listQueryParamNames1() {
if(config1 == null || config1.equals(null)){
System.out.println("CXF config test: config1 is null");
} else{
System.out.println("CXF config test: config1 is not null:
" +
config1.toString());
}
if(config2 == null || config2.equals(null)){
System.out.println("CXF config test: config2 is null");
} else{
System.out.println("CXF config test: config2 is not null:
" +
config2.toString());
}
return ContextUtil.URIINFONAME1 + ": " +
ContextUtil.testUriInfo(uriInfo1);
}
All other @context injection work fine, such as uriinfo, request,
httpheaders and so on...
But only Configuration doesn't work
My test report:
CXF config test: config1 is null
CXF config test: config2 is null
Sometime, I also see this error:
Caused by: java.lang.NullPointerException: javax.ws.rs.core.Configuration
context class has not been injected. Check if ContextProvider supporting
this class is registered
This is to do with a fact CXF is lax with accepting custom interfaces
(and given it does not support the injection of Configuration it comes
up as a custom interface). So what happens a thread local proxy is
injected but at the runtime, if it is accessed, NPE will be reported if
an actual (custom) ContextProvider is available, see
https://issues.apache.org/jira/browse/CXF-5803,
we agreed with Andrey who reported the issue originally that if a custom
context resolver is not available then a thread local proxy should not
even be created - another issue to take care of. We do not have a
resource leak but it would simply be cleaner and more optimal.
*2, Does @Context work/available in Application class?*
I write some injection in Application like this:
@ApplicationPath("/context")
public class DemoApplication extends javax.ws.rs.core.Application {
@Context
private UriInfo ui;
@Context
private HttpHeaders hh;
@Context
private Request re;
@Context
private Application ap;
@Context
private ResourceContext rc;
@Context
private Providers pr;
But I cannot use them in anywhere in Application code, all report
null. is
this work as design?
And I see the standard, we could use @Context for Constructor.
If we cannot use @Context in Application, how can we new Resource for
Singleton?
Such as, here is my resource Constructor :
public AbstractRestService(@Context UriInfo ui, @Context
HttpHeaders hh,
@Context Request r, @Context Providers p) {
this.uriInfo3 = ui;
this.httpheaders3 = hh;
this.request3 = r;
this.providers3 = p;
}
When init, getClasses() works fine because we don't need write
Constructor.
But getSingletons() doesn't work, because I need provide @context in
Application:
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(ClassesRestService.class);
classes.add(ClassesRestService2.class);
classes.add(ContextRequestFilter1.class);
classes.add(ContextRequestFilter2.class);
classes.add(ContextRequestFilter3.class);
classes.add(ContextRequestFilter4.class);
classes.add(JordanExceptionMapProvider.class);
return classes;
}
@Override
public Set getSingletons() {
Set objs = new HashSet();
* objs.add(new SingletonsRestService(ui, hh, re, pr));*
objs.add(new SingletonsRestService2(rc));
objs.add(new ContextRequestFilter1());
objs.add(new ContextRequestFilter2());
// objs.add(new ContextRequestFilter3(ui, ap, pr));
objs.add(new ContextRequestFilter4());
objs.add(new JordanExceptionMapProvider());
return objs;
}
I have tested by using CXF, they all don't work, and I didn't see any
related test in CXF project.
Hmm... Application itself can definitely be injected as a Context into
providers/resource classes.
I have to admit, the use case you've described above is entirely new to
me. Right, the constructor injection in getClasses() would indeed work,
but not in getSingletons()...
By the way, where exactly do you see that contexts can be injected into
Application ? Actually, here:
"9.2
Context Types
This section describes the types of context available to resource
classes, providers and Application sub-
classes."
Yes, will be fixed asap.
Could you please help take a look?
Thanks all and have a good day~ :)
Thanks for the detailed analysis, appreciated
Cheers. Sergey
--
View this message in context:
http://cxf.547215.n5.nabble.com/Configuration-and-Constructor-Context-Injection-problem-when-using-CXF-tp5747973.html
Sent from the cxf-dev mailing list archive at Nabble.com.