arquillian / arquillian-extension-rest

Declarative REST testing extension
37 stars 20 forks source link

ClassCastException is thrown if Jersey is used. #14

Open lordofthejars opened 10 years ago

lordofthejars commented 10 years ago

I am using Arquillian-Rest-Extension to test REST services. The server part is implemented using Jersey (not RestEasy). The problem is that when query params are set a classcastexception is thrown.

java.lang.ClassCastException: org.glassfish.jersey.uri.internal.JerseyUriBuilder cannot be cast to org.jboss.resteasy.specimpl.ResteasyUriBuilder
    at org.jboss.resteasy.client.jaxrs.internal.ClientWebTarget.queryParamNoTemplate(ClientWebTarget.java:287)
    at org.jboss.resteasy.client.jaxrs.internal.proxy.processors.webtarget.QueryParamProcessor.apply(QueryParamProcessor.java:23)
    at org.jboss.resteasy.client.jaxrs.internal.proxy.processors.webtarget.QueryParamProcessor.apply(QueryParamProcessor.java:12)

The problem is at line 287 where there are a clone and a cast:

ResteasyUriBuilder copy = (ResteasyUriBuilder)uriBuilder.clone();
for (String obj : stringValues)
{
    copy.clientQueryParam(name, obj);
}

copy should be casted not to the interface UriBuilder but to ResteasyUriBuilder because clientQueryParam is a method from that class. Of course it can be very solutions to that problem:

WDYT?

blabno commented 10 years ago

@lordofthejars This code should be run only in @RunAsClient mode because rest client is rest created only using RestEasy. Although John Ament has created pure JAX-RS impl of the extension. But allow me to look at it later today.

lordofthejars commented 10 years ago

Take your time don't worry. BTW The test is already run with @RunAsClient annotation. If you need I will push the code to github, there is no problem about that.

blabno commented 10 years ago

@lordofthejars such testcase would be very welcome.

lordofthejars commented 10 years ago

This afternoon (20:00 CET) I will push the code and send you the link. Thank you so much.

2014/1/8 Bernard Labno notifications@github.com

@lordofthejars https://github.com/lordofthejars such testcase would be very welcome.

— Reply to this email directly or view it on GitHubhttps://github.com/arquillian/arquillian-extension-rest/issues/14#issuecomment-31812825 .

+----------------------------------------------------------+ Alex Soto Bueno - Computer Engineer www.lordofthejars.com +----------------------------------------------------------+

lordofthejars commented 10 years ago

Pushed at https://github.com/lordofthejars/chapter-9/blob/arquillian-rest-extension/src/it/java/com/wakaleo/bddinaction/chapter9/flightstatus/WhenIWantToKnowFlightsByDeparture.java on arquillian-rest-extension branch.

juancasta commented 10 years ago

Hello.

I am facing same problem. I want to user arquillian persistence extension with webservices deployed in glassfish, so the implementation is Jersey.

Did you solve it? I am checking the code in te repo.

Thanks.

lordofthejars commented 10 years ago

I have git a running example with apache TomEE which used apache cxf and I remember doing some hacking let me find the example and I send you the link

Enviat des del meu iPhone

El 16/05/2014, a les 11.33, juancasta notifications@github.com va escriure:

Hello.

I am facing same problem. I want to user arquillian persistence extension with webservices deployed in glassfish, so the implementation is Jersey.

Did you solve it? I am checking the code in te repo.

Thanks.

— Reply to this email directly or view it on GitHub.

juancasta commented 10 years ago

Thanks!

blabno commented 10 years ago

maybe exclude Jersey dependency from test?¿ But then server won't receive it and I need it because it is a Tomcat.

I think that the problem is embedded mode for Tomcat. As I understand it, Tomcat uses same classpath as tests, so in order for Tomcat to run with Jersey, it needs to be on classpath, but this way, dependencies of RestEasy Client (used by our extension) get substituted by jersey.

Solution 1 (not perfect): avoid embedded mode and run in managed mode. Solution 2: implement Jersey impl for the extension.

blabno commented 10 years ago

I've created prototype of jersey impl of our extension:

package org.jboss.arquillian.extension.rest.client;

import org.glassfish.jersey.client.JerseyClientBuilder;
import org.glassfish.jersey.client.JerseyWebTarget;
import org.glassfish.jersey.client.proxy.WebResourceFactory;
import org.jboss.arquillian.test.spi.TestEnricher;

import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.WebTarget;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class RestEnricher extends BaseRestEnricher implements TestEnricher {

    @Override
    protected boolean isSupportedParameter(Class<?> clazz) {
        return true; // it's proxy based, exception will be thrown when proxying.
    }

    @Override
    protected Object enrichByType(Class<?> clazz, Method method,
                                  ArquillianResteasyResource annotation, Consumes consumes, Produces produces) {
        Object value = null;
        Client client = JerseyClientBuilder.newClient();
        WebTarget webTarget = client.target(getBaseURL() + ((ArquillianResteasyResource) annotation).value());
        JerseyWebTarget jerseyWebTarget = (JerseyWebTarget) webTarget;
        if (JerseyWebTarget.class.isAssignableFrom(clazz)) {
            value = jerseyWebTarget;
        } else {
            final Class<?> parameterType;
            try {
                final Annotation[] methodDeclaredAnnotations = method.getDeclaredAnnotations();
//                                This is test method so if it only contains @Test annotation then we don't need to hassel with substitutions
                parameterType = methodDeclaredAnnotations.length <= 1 ? clazz : ClassModifier.getModifiedClass(clazz, methodDeclaredAnnotations);
            } catch (Exception e) {
                throw new RuntimeException("Cannot substitute annotations for method " + method.getName(), e);
            }
            value = WebResourceFactory.newResource(clazz, jerseyWebTarget);
        }
        return value;
    }

}
blabno commented 10 years ago

@lordofthejars Could you have a look at getCustomerById test? https://github.com/blabno/arquillian-extension-rest/commit/03a6959d6f4f42c60211dc5873814b7fbc708de5#diff-c84ee3844f0ecbbefcbecf1202a011f3R113

If I run it in tomcat-embedded profile (Jersey on server side). I'm getting 404.

lordofthejars commented 10 years ago

In remote it works right?

Enviat des del meu iPhone

El 19/05/2014, a les 14.45, Bernard Labno notifications@github.com va escriure:

@lordofthejars Could you have a look at getCustomerById test? blabno@03a6959#diff-c84ee3844f0ecbbefcbecf1202a011f3R113

If I run it in tomcat-embedded profile (Jersey on server side). I'm getting 404.

— Reply to this email directly or view it on GitHub.

blabno commented 10 years ago

I haven't tested it with remote tomcat just managed as7 and embedded tomcat. 19 maj 2014 15:10 "Alex Soto" notifications@github.com napisał(a):

In remote it works right?

Enviat des del meu iPhone

El 19/05/2014, a les 14.45, Bernard Labno notifications@github.com va escriure:

@lordofthejars Could you have a look at getCustomerById test? blabno@03a6959#diff-c84ee3844f0ecbbefcbecf1202a011f3R113

If I run it in tomcat-embedded profile (Jersey on server side). I'm getting 404.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHubhttps://github.com/arquillian/arquillian-extension-rest/issues/14#issuecomment-43499929 .

lordofthejars commented 10 years ago

If you Can try with managed/remote tomcat if it works it is a dependencies problem if not I will take a look this night

El dilluns, 19 maig de 2014, Bernard Labno notifications@github.com va escriure:

I haven't tested it with remote tomcat just managed as7 and embedded tomcat. 19 maj 2014 15:10 "Alex Soto" notifications@github.com<javascript:_e(%7B%7D,'cvml','notifications@github.com');> napisał(a):

In remote it works right?

Enviat des del meu iPhone

El 19/05/2014, a les 14.45, Bernard Labno notifications@github.com<javascript:_e(%7B%7D,'cvml','notifications@github.com');> va escriure:

@lordofthejars Could you have a look at getCustomerById test? blabno@03a6959#diff-c84ee3844f0ecbbefcbecf1202a011f3R113

If I run it in tomcat-embedded profile (Jersey on server side). I'm getting 404.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub< https://github.com/arquillian/arquillian-extension-rest/issues/14#issuecomment-43499929>

.

— Reply to this email directly or view it on GitHubhttps://github.com/arquillian/arquillian-extension-rest/issues/14#issuecomment-43500099 .

Enviat amb Gmail Mobile

blabno commented 10 years ago

It works with managed Tomcat, so I'll try to check the dependencies again.

Well, actually it does not work.

lordofthejars commented 10 years ago

Ok then try to do next:

https://github.com/lordofthejars/bjugbank/blob/master/pom.xml#L173

I have used for TomEE embedded but probably something similar to Tomcat should be done but changing the dependency to Jersey. If it works then I explain why it happens :)

2014-05-20 9:03 GMT+02:00 Bernard Labno notifications@github.com:

It works with managed Tomcat, so I'll try to check the dependencies again.

— Reply to this email directly or view it on GitHubhttps://github.com/arquillian/arquillian-extension-rest/issues/14#issuecomment-43592527 .

+----------------------------------------------------------+ Alex Soto Bueno - Computer Engineer www.lordofthejars.com +----------------------------------------------------------+

blabno commented 10 years ago

@lordofthejars I have commited Tomcat managed profile, but the problem with getCustomerById remains.

blabno commented 10 years ago

What a stupid issue! I've just noticed that CustomerResourceImpl.getCustomerById has JAX-RS annotation. If I remove it and leave annotations only on CustomerResource interface then everything woks.

public Customer getCustomerById(@PathParam("id") long id)
lordofthejars commented 10 years ago

Ou yes sorry, I remembered now that annotations should go into interface not in the class itself. I found the same problem in my example and I fix it, but now I was not aware that it could happens the same to you :S.

Cool!!!

2014-05-20 10:51 GMT+02:00 Bernard Labno notifications@github.com:

What a stupid issue! I've just noticed that CustomerResourceImpl.getCustomerById has JAX-RS annotation. If I remove it and leave annotations only on CustomerResourceinterface then everything woks.

public Customer getCustomerById(@PathParam("id") long id)

— Reply to this email directly or view it on GitHubhttps://github.com/arquillian/arquillian-extension-rest/issues/14#issuecomment-43600923 .

+----------------------------------------------------------+ Alex Soto Bueno - Computer Engineer www.lordofthejars.com +----------------------------------------------------------+