jersey
  1. jersey
  2. JERSEY-747

Jersey client unable to unmarshal a custom type using SortedSet

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Invalid
    • Affects Version/s: 1.8
    • Fix Version/s: 1.17
    • Component/s: core
    • Labels:
      None
    • Environment:

      Jersey 1.9-SNAPSHOT, GlassFish 3.1, Sun JDK 6 update 26

      Description

      Client
      public void sendJerseyRequest() {
          ClientConfig cc = new DefaultClientConfig();
          cc.getSingletons().add(MovieSetMessageBodyReader.class);
          Client client = Client.create(cc);
          WebResource webResource = client.resource(GLASSFISH_ENDPOINT_URI);
          webResource.accept(MediaType.TEXT_XML);
          GenericType<OrderedAssembly<Movie>> assemblyType = new GenericType<OrderedAssembly<Movie>>() {
          };
          System.out.println("sendJerseyRequest: " + assemblyType.getRawClass());
          System.out.println("sendJerseyRequest: " + assemblyType.getType());
          OrderedAssembly<Movie> movies = webResource.queryParam("path", PATH)
              .get(assemblyType);
      
          System.out.println(movies);
          }
      
      Log
      Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.76 sec <<< FAILURE!
      testSendJerseyRequest(name.app.abhi.movieservice.ejb.restful.client.MovieServiceEjbRestfulClientTest)  Time elapsed: 0.666 sec  <<< ERROR!
      java.lang.IllegalArgumentException: Invalid type parameter e1: com.sun.org.apache.xerces.internal.dom.ElementNSImpl. Only name.app.abhi.moviemanager.domain.Movie accepted.
          at name.app.abhi.moviemanager.service.impl.MovieComparator.compare(MovieComparator.java:14)
          at java.util.TreeMap.put(TreeMap.java:530)
          at java.util.TreeSet.add(TreeSet.java:238)
          at com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.addToPack(Lister.java:290)
          at com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.addToPack(Lister.java:254)
          at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Scope.add(Scope.java:106)
      
      Movie.java
      @XmlAccessorType(XmlAccessType.FIELD)
      @XmlType(name = "movie", propOrder = { "name", "year", "genre", "filesize",
          "fileExtension", "parent" })
      public class Movie implements Serializable {
          // fields, getters and setters
      }
      
      OrderedAssembly.java
      @XmlRootElement(name = "movie-set", namespace = "http://name.app.abhi/movieservice")
      @XmlType
      @XmlAccessorType(XmlAccessType.FIELD)
      public class OrderedAssembly<Movie> {
      
          @XmlElement(name = "movie")
          SortedSet<Movie> elements = new TreeSet<Movie>(new MovieComparator<Movie>());
      
          public OrderedAssembly() {
          }
      
          public OrderedAssembly(SortedSet<Movie> ss) {
          addAll(ss);
          }
      
          public OrderedAssembly(SortedSet<Movie> ss, Comparator<Movie> comparator) {
          elements = new TreeSet<Movie>(comparator);
      
          addAll(ss);
          }
      
          public SortedSet<Movie> getElements() {
          return elements;
          }
      
          private void addAll(SortedSet<Movie> ss) {
          if (ss != null) {
              elements.clear();
              elements.addAll(ss);
          }
          }
      }
      

        Activity

        Hide
        Pavel Bucek added a comment -

        any thought why the exception is being thrown from MovieComparator class?

        can you share complete (minimal) testcase (it would definitely speed things up..)?

        Show
        Pavel Bucek added a comment - any thought why the exception is being thrown from MovieComparator class? can you share complete (minimal) testcase (it would definitely speed things up..)?
        Hide
        abhi0123 added a comment -

        Exception is thrown from MovieComparator because it (rightfully) does an instanceof check before proceeding to compare 2 movies.
        The test case just calls the sendJerseyRequest() request (see below). If you are asking me to provide code that you can actually execute, I will have to create an entirely new one. The current project is a large one with some local dependencies and can't be easily exported.

        Movie.java
        @Override
            public int compare(E e1, E e2) {
        	if (!(e1 instanceof Movie)) {
        	    throw new IllegalArgumentException("Invalid type parameter e1: "
        		    + e1.getClass().getName() + ". Only "
        		    + Movie.class.getName() + " accepted.");
        	}
        
        	if (!(e2 instanceof Movie)) {
        	    throw new IllegalArgumentException("Invalid type parameter e2: "
        		    + e2.getClass().getName() + ". Only "
        		    + Movie.class.getName() + " accepted.");
        	}
        
        	Movie m1 = (Movie) e1;
        	Movie m2 = (Movie) e2;
                // comparison code
        }
        
        MovieServiceEjbRestfulClientTest
        public class MovieServiceEjbRestfulClientTest {
        
            @Test
            public void testSendJerseyRequest() {
        	new MovieServiceEjbRestfulClient().sendJerseyRequest();
            }
        }
        
        Show
        abhi0123 added a comment - Exception is thrown from MovieComparator because it (rightfully) does an instanceof check before proceeding to compare 2 movies. The test case just calls the sendJerseyRequest() request (see below). If you are asking me to provide code that you can actually execute, I will have to create an entirely new one. The current project is a large one with some local dependencies and can't be easily exported. Movie.java @Override public int compare(E e1, E e2) { if (!(e1 instanceof Movie)) { throw new IllegalArgumentException( "Invalid type parameter e1: " + e1.getClass().getName() + ". Only " + Movie.class.getName() + " accepted." ); } if (!(e2 instanceof Movie)) { throw new IllegalArgumentException( "Invalid type parameter e2: " + e2.getClass().getName() + ". Only " + Movie.class.getName() + " accepted." ); } Movie m1 = (Movie) e1; Movie m2 = (Movie) e2; // comparison code } MovieServiceEjbRestfulClientTest public class MovieServiceEjbRestfulClientTest { @Test public void testSendJerseyRequest() { new MovieServiceEjbRestfulClient().sendJerseyRequest(); } }
        Hide
        Pavel Bucek added a comment -

        ok, thanks. I can recreate similar testcase by myself but it might take some time.

        I will keep this issue updated.

        Show
        Pavel Bucek added a comment - ok, thanks. I can recreate similar testcase by myself but it might take some time. I will keep this issue updated.
        Hide
        Pavel Bucek added a comment -

        Ok, I managed to recreate your sample in my environment.. and I got it working.

        The key part and .. question I should have asked before is: "Why are you using your own MovieSetMessageBodyReader?". It does make sense, since it can't be unmarshalled without it. The problem here is that JAXBContext created for unmarshalling your type doesn't know about Movie.class, which can be easily fixed and you don't need to create your own message body reader (btw I still don't now what are you doing there).

        CustomContextResolver
        @Provider
        public class CustomContextResolver implements ContextResolver<JAXBContext> {
        
            @Override
            public JAXBContext getContext(Class<?> type) {
                // if type != OrderedAssembly.class return null
                try {
                    return JAXBContext.newInstance(OrderedAssembly.class, Movie.class);
                } catch(Exception e) {
                    return null;
                }
            }
        
        }
        client code
                ClientConfig cc = new DefaultClientConfig();
                cc.getSingletons().add(new CustomContextResolver());
                Client c = Client.create(cc);
                webResource = c.resource(getURI());
        
                OrderedAssembly<Movie> set = webResource.path("helloworld/set").get(new GenericType<OrderedAssembly<Movie>>() {});
                ...
        

        to be honest, I don't know how did you managed to produce this response (I can't see "service" code in your sample) without already having your custom JAXBContext resolver somewhere..

        Anyway - closing as invalid. I can share my test if you want to see it. Feel free to reopen if you can share more info/testcase.

        Show
        Pavel Bucek added a comment - Ok, I managed to recreate your sample in my environment.. and I got it working. The key part and .. question I should have asked before is: "Why are you using your own MovieSetMessageBodyReader?". It does make sense, since it can't be unmarshalled without it. The problem here is that JAXBContext created for unmarshalling your type doesn't know about Movie.class, which can be easily fixed and you don't need to create your own message body reader (btw I still don't now what are you doing there). CustomContextResolver @Provider public class CustomContextResolver implements ContextResolver<JAXBContext> { @Override public JAXBContext getContext( Class <?> type) { // if type != OrderedAssembly.class return null try { return JAXBContext.newInstance(OrderedAssembly.class, Movie.class); } catch (Exception e) { return null ; } } } client code ClientConfig cc = new DefaultClientConfig(); cc.getSingletons().add( new CustomContextResolver()); Client c = Client.create(cc); webResource = c.resource(getURI()); OrderedAssembly<Movie> set = webResource.path( "helloworld/set" ).get( new GenericType<OrderedAssembly<Movie>>() {}); ... to be honest, I don't know how did you managed to produce this response (I can't see "service" code in your sample) without already having your custom JAXBContext resolver somewhere.. Anyway - closing as invalid. I can share my test if you want to see it. Feel free to reopen if you can share more info/testcase.

          People

          • Assignee:
            Pavel Bucek
            Reporter:
            abhi0123
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: