Skip to content
This repository has been archived by the owner on Dec 15, 2018. It is now read-only.

InjectParamsTest TCK test failure with CXF #168

Open
chkal opened this issue May 18, 2018 · 23 comments
Open

InjectParamsTest TCK test failure with CXF #168

chkal opened this issue May 18, 2018 · 23 comments

Comments

@chkal
Copy link
Contributor

chkal commented May 18, 2018

The TCK verifies that parameters can be injected into resource fields and properties as required by the JAX-RS spec.

Unfortunately one of the tests fails with CXF.

[INFO] Results:
[INFO] 
[ERROR] Failures: 
[ERROR]   InjectParamsTest.injectFieldParam:119 
Expected: a string containing "Value = 'foo-bar'"
     but: was "Value = ''"
[INFO] 
[ERROR] Tests run: 5, Failures: 1, Errors: 0, Skipped: 0

This test basically verifies, that a resource field can be annotated with @QueryParam and that the value of a corresponding parameter is injected into this field.

https://github.com/mvc-spec/mvc-tck/blob/c050db27be170ff8fc7f0f41ab61e45c6b69fcc7/tests/src/main/java/org/mvcspec/tck/tests/mvc/controller/inject/InjectParamsController.java#L35-L36

I don't understand why this fails. It works fine with Glassfish and Wildfly. I don't think that this is something caused by Ozark. Perhaps CXF doesn't support injection into resources fields correctly?

It would be great if somebody could help verifying this.

@Daniel-Dos
Copy link
Contributor

Daniel-Dos commented Jul 10, 2018

Hi @chkal ,

I did the test without Ozark, following the same TCK model, and it executes and displays the output when @QueryParam is used in an attribute.

with Ozark this value is Null .

test using TomEE 7.0.4 and 7.0.5

@chkal
Copy link
Contributor Author

chkal commented Jul 11, 2018

That's weird. I don't know why Ozark could cause this. Maybe because Ozark ships with a custom ParameterConverterProvider?

Could you perhaps debug if this method is executed and how it behaves?

https://github.com/mvc-spec/ozark/blob/master/core/src/main/java/org/mvcspec/ozark/binding/convert/MvcConverterProvider.java#L54

Perhaps you could even debug how the CXF code calling MvcConverterProvider.getConverter() handles the null returned from our implementation. From my understanding it should continue do look for other provider and finally find the default one provided by CXF.

@Daniel-Dos
Copy link
Contributor

I will look too .

@Daniel-Dos
Copy link
Contributor

Daniel-Dos commented Aug 6, 2018

Hi @chkal ,

I made the debug, but I could not identify the default CXF, after it passes the MVCConverterProvider.getConverter () it comes null and then the same goes to the following method of the CXF class:

Class ProviderFactory

public <T> ParamConverter<T> createParameterHandler(Class<T> paramType, 
                                                        Type genericType,
                                                        Annotation[] anns,
                                                        Message m) {
        
        anns = anns != null ? anns : new Annotation[]{};
        for (ProviderInfo<ParamConverterProvider> pi : paramConverters) {
            injectContextValues(pi, m);
            ParamConverter<T> converter = pi.getProvider().getConverter(paramType, genericType, anns);
            if (converter != null) {
                return converter;
                pi.clearThreadLocalProxies();
            }
        }
        return null;
    }

here in the case the ParamConverter <T> convert = pi.getProvider (). getConverter (paramType, genericType, anns); is null and the following is directed to the following CXF class method:

class InjectionsUtils

public static <T> T createFromParameterHandler(String value, 
                                                    Class<T> pClass,
                                                    Type genericType,
                                                    Annotation[] anns,
                                                    Message message) {
        T result = null;
        if (message != null) {
            ServerProviderFactory pf = ServerProviderFactory.getInstance(message);
            ParamConverter<T> pm = pf.createParameterHandler(pClass, genericType, anns, message);
            if (pm != null) {
                result = pm.fromString(value);
            }
        }
        return result;
    }

it can idendify the value passed by the @QueryParam, but in the end it returns null

now using @QueryParam as paramenter in the method it works normal with Ozark.

Now without Ozark, the InjectParam will work with CXF.

@chkal
Copy link
Contributor Author

chkal commented Aug 7, 2018

Thanks for sharing this analysis. Do you have the sample app available you used for this?

@Daniel-Dos
Copy link
Contributor

Hi @chkal ,

can I do, in case you one with Ozark and another without? step a zip here or a link to some repository.

@chkal
Copy link
Contributor Author

chkal commented Aug 7, 2018

Awesome! A link to a repository would be great!

@Daniel-Dos
Copy link
Contributor

Hi @chkal ,

follows the examples with InjectParam with and without Ozark, I did the tests with TomEE 7.0.5.

https://github.com/Daniel-Dos/InjectParamsTest-Ozark-CXF

@chkal
Copy link
Contributor Author

chkal commented Aug 14, 2018

Thanks @Daniel-Dos. I'll have a look, but it may take some time, as I'm on vacation for the next two weeks.

@chkal
Copy link
Contributor Author

chkal commented Sep 7, 2018

I experimented a bit with this issue. It is really weird. Using `@QueryParam' on a resource field doesn't work, but it is working fine if I place the annotation on the corresponding getter instead.

Also the issue is occurring even if I don't register MvcConverterProvider at all. So it looks like it has nothing to do with Ozark directly. At least this is my guess.

I just created CXF-7834 with a description of my observations. Let's see what they think about this issue.

@Daniel-Dos
Copy link
Contributor

wonderful.

It really is pretty weird.

even with the response of the CXF team, could not reproduce what happened.

Now it is investigating if it is some component that Ozark uses that is generating this problem

thank you.

@chkal
Copy link
Contributor Author

chkal commented Sep 8, 2018

I'm not really sure what is causing this. I'm planning to setup some minimal sample environment (Tomcat + CXF + Weld) to see if I can reproduce it there. I don't think that Ozark is causing this. I removed our ParamConverterProvider and the issue still occurred. This is really weird.

@Daniel-Dos
Copy link
Contributor

I get it, it's really weird.

@dmaidaniuk
Copy link
Contributor

Hi @chkal & @Daniel-Dos ,

I made a bit more debugging of reproducer applications from Daniel and found a reason for this bug. I used TomEE 7.1.0 plus for this investigation. It contains CXF v.3.1.15 library.
In case of pure CXF application for next call trace

injectFieldValue:224, InjectionUtils (org.apache.cxf.jaxrs.utils)
injectParameters:295, JAXRSUtils (org.apache.cxf.jaxrs.utils)
injectContexts:349, ClassResourceInfo (org.apache.cxf.jaxrs.model)
invoke:161, JAXRSInvoker (org.apache.cxf.jaxrs)
invoke:101, JAXRSInvoker (org.apache.cxf.jaxrs)
invoke:68, AutoJAXRSInvoker (org.apache.openejb.server.cxf.rs)
run:59, ServiceInvokerInterceptor$1 (org.apache.cxf.interceptor)
handleMessage:96, ServiceInvokerInterceptor (org.apache.cxf.interceptor)
doIntercept:308, PhaseInterceptorChain (org.apache.cxf.phase)
onMessage:121, ChainInitiationObserver (org.apache.cxf.transport)
invoke:267, AbstractHTTPDestination (org.apache.cxf.transport.http)
doInvoke:253, CxfRsHttpListener (org.apache.openejb.server.cxf.rs)
doFilter:94, CXFJAXRSFilter (org.apache.tomee.webservices)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:52, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:65, EEFilter (org.apache.openejb.server.httpd)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
invoke:198, StandardWrapperValve (org.apache.catalina.core)
invoke:96, StandardContextValve (org.apache.catalina.core)
invoke:44, OpenEJBValve (org.apache.tomee.catalina)
invoke:493, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:140, StandardHostValve (org.apache.catalina.core)
invoke:81, ErrorReportValve (org.apache.catalina.valves)
invoke:97, OpenEJBSecurityListener$RequestCapturer (org.apache.tomee.catalina)
invoke:650, AbstractAccessLogValve (org.apache.catalina.valves)
invoke:87, StandardEngineValve (org.apache.catalina.core)
service:342, CoyoteAdapter (org.apache.catalina.connector)
service:800, Http11Processor (org.apache.coyote.http11)
process:66, AbstractProcessorLight (org.apache.coyote)
process:800, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1471, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)

we have in method InjectionUtils#injectFieldValue(...) a pure instance of JAX-RS controller:

cxf-only

So finally field fieldValue set correctly and showed on UI.

But in the case of Ozark + CXF application, we have an instance of OwbInterceptorProxy for injection. And real instance of the Controller class not changed there:

ozark-cxf-proxy
That's why when end-point's method invoked we will have null value in field fieldValue.

So, for me, it looks like a problem with the integration of CXF and OpenWebBeans. CXF doesn't understand that it works with CDI proxy and thus it doesn't inject query param properly.

I will try to prepare reproducer project only with JAX-RS and CDI components.

Regards,
Dmytro

@dmaidaniuk
Copy link
Contributor

It is funny that CXF actually has a mechanism to detect proxies in class ClassResourceInfo:

public void injectContexts(Object resourceObject, OperationResourceInfo ori, Message inMessage) {
        final boolean contextsAvailable = contextsAvailable();
        final boolean paramsAvailable = paramsAvailable();
        if (contextsAvailable || paramsAvailable) {
            Object realResourceObject = ClassHelper.getRealObject(resourceObject);
            if (paramsAvailable) {
                JAXRSUtils.injectParameters(ori, this, realResourceObject, inMessage);
            }
            if (contextsAvailable) {
                InjectionUtils.injectContexts(realResourceObject, this, inMessage);
            }
        }
}

However, check ClassHelper.getRealObject(resourceObject) doesn't work as OwbInterceptorProxy doesn't register itself as java.lang.reflect.Proxy. :)
So, it is more like a bug in OpenWebBeans project.

@dmaidaniuk
Copy link
Contributor

It is enough to add annotation javax.enterprise.context.RequestScoped into class InjectParams from Daniel's example application and also add beans.xml to the resources folder. This will generate $OwbNormalScopeProxy instance instead of $OwbInterceptProxy. However, the current issue reproduces for this proxy too.

@chkal
Copy link
Contributor Author

chkal commented Sep 23, 2018

AWESOME! Thanks a lot @dmaidaniuk for digging into this. I already assumed that it has something to do with the CDI integration.

I just reopened CXF-7834 and included a link to your summary. I hope that this will help the CXF devs to reproduce this.

If anyone already has a minimal sample app (without Ozark) that reproduces this, feel free to attach it to the upstream CXF issue.

Thanks!

@Daniel-Dos
Copy link
Contributor

Hi @dmaidaniuk ,

very good.

I made the change in the example as presented by you.

thank you so much.

@chkal
Copy link
Contributor Author

chkal commented Oct 3, 2018

Hi all. There is a new comment in the upstream CXF issue. Did anyone ever create a reproducer for the latest CXF version? Maybe a sample app which contains OWB and CXF in WEB-INF/lib and can be deployed to plain Tomcat?

@Daniel-Dos
Copy link
Contributor

Daniel-Dos commented Oct 3, 2018

Hi @chkal,

I can try to create an example later using CXF 3.2.6.

http://cxf.apache.org/download.html

@chkal
Copy link
Contributor Author

chkal commented Oct 3, 2018

@Daniel-Dos That would be awesome! 🍻

@Daniel-Dos
Copy link
Contributor

Hi @chkal ,

I did the test using the latest version of CXF CXF 3.2.6 and also did it with 3.1.17 with Tomcat.

but the injection of param paramenter does not work, still returns blank although it has taken the information as in the image.

cxf

The example is in this link :

https://github.com/Daniel-Dos/InjectParamsTest-Ozark-CXF/tree/master/OnlyCXFTomcat

with following endpoint : http://localhost:8080/only.cxf.tomcat/rest/app/hello/param?fieldValue=ola

doc :

http://cxf.apache.org/docs/using-cxf-and-cdi-11-jsr-346.html

@chkal
Copy link
Contributor Author

chkal commented Oct 4, 2018

Great! Thanks a lot! Could you post a link to your example in the upstream issue CXF-7834?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants