Unmarshalling XML or JSON to render an entered object in a knitwear using the @InjectParam annotation

I am having a problem with sorting XML data correctly. I use guice and jersey technology. The strange thing is that when I try to parse manually using JAXB, everything works fine:

StringBuilder xml = new StringBuilder();
xml.append("<role>");
xml.append("  <name><values><value>Administrator</value><value l=\"en\">Administrator</value></values></name>");
xml.append("  <permissions>");
xml.append("    <permission>READ_XX</permission>");
xml.append("    <permission>WRITE_XX</permission>");
xml.append("  </permissions>");
xml.append("</role>");

JAXBContext jaxbContext = JAXBContext.newInstance(DefaultRole.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Object o = jaxbUnmarshaller.unmarshal(new StringReader(xml.toString()));

As a result, I get a correctly populated object: DefaultRole [id = null, name = [{val = Administrator}, {l = en, val = Administrator}], permissions = [READ_XX, WRITE_XX]]

However, when you try to use jersey and enter my role interface, it does not work:

@POST
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public JSONObject processLogin(@InjectParam Role role) throws JSONException
{
  System.out.println(role);

  return null;
}

The object is created but not populated: DefaultRole [id = null, name = null, permissions = []]

It is strange that when I replace the interface parameter (@InjectParam role role) with the default class:

@POST
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public JSONObject processLogin(DefaultRole role) throws JSONException
{
  System.out.println(role);

  return null;
}

, .

, , ?

DefaultRole :

@XmlRootElement(name = "role")
@XmlAccessorType(XmlAccessType.FIELD)
public class DefaultRole implements Role
{
  private Id id = null;

  @XmlJavaTypeAdapter(ContextObjectAdapter.class)
  private ContextObject<String> name = null;

  @XmlElementWrapper(name = "permissions")
  @XmlElement(name = "permission")
  private List<String> permissions = Lists.newArrayList();

  @Inject
  private DefaultRole()
  {
  }
  [...]

JAXB , . - . , .

. ,

web.xml:

WEB-INF, , , (, web.xml, ):

    Injector injector = ModuleInjector.get().createChildInjector(new JerseyServletModule()
    {
        @Override
        protected void configureServlets()
        {
            bind(GuiceContainer.class);

            Set<Class<?>> foundClasses1 = Reflect.getReflections().getTypesAnnotatedWith(Path.class, false);
            Set<Class<?>> foundClasses2 = Reflect.getReflections().getTypesAnnotatedWith(Provider.class, false);

            Set<Class<?>> foundClasses = Sets.newHashSet();
            foundClasses.addAll(foundClasses1);
            foundClasses.addAll(foundClasses2);

            if (foundClasses != null && foundClasses.size() > 0)
            {
                for (Class<?> foundClass : foundClasses)
                {
                    if (foundClass == null)
                        continue;

                    if (ResourceConfig.isProviderClass(foundClass)
                        || ResourceConfig.isRootResourceClass(foundClass))
                    {
                        bind(foundClass);
                    }
                }
            }

            serve("/restws/*").with(GuiceContainer.class, ImmutableMap.of(JSONConfiguration.FEATURE_POJO_MAPPING, "true"));
        }
    });

, . web.xml:

    <!-- WHERE THE JERSEY COMPONENTS ARE BEING REGISTERED -->
<filter>
     <display-name>Bootstrap Filter</display-name>
     <filter-name>BootstrapFilter</filter-name>
     <filter-class>xxx.BootstrapFilter</filter-class>
 </filter>

<filter>
    <filter-name>Guice Filter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>


    <!-- WHERE THE JERSEY COMPONENTS ARE BEING REGISTERED -->
<filter-mapping>
    <filter-name>BootstrapFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

<filter-mapping>
    <filter-name>Guice Filter</filter-name>
    <url-pattern>/restws/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
+3
1

, , , , , . :

" 2.0 Guice. https://java.net/jira/browse/JERSEY-1950". (http://jersey.576304.n2.nabble.com/Guice-integration-td7581958.html)

. , , , , :

  • , , "" .
  • , , ( ?).
  • .

beans @Model "". , , . , , @InjectParam.

, , :

    model = request.getEntity(model.getClass());" 

, guice, ( , JSON XML). , @InjectParam , , - ​​ .

, :

  • "ModelParam" :

    @Target({ PARAMETER, METHOD, FIELD })
    @Retention(RUNTIME)
    @Documented
    public @interface ModelParam
    {
    }
    
  • "InjectParam" "RoleRestWS" "ModelParam" :

    @POST
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public Role createRole(@ModelParam Role role) throws JSONException
    {
      return userService.createRole(role);
    }
    
  • InjectableProvider "ModelParam" :

    @Provider
    @Singleton
    public class ModelInjectableProvider extends AbstractHttpContextInjectable<Model> implements InjectableProvider<ModelParam, Type>
    {
        private final Type type;
    
        public ModelInjectableProvider()
        {
            type = null;
        }
    
        public ModelInjectableProvider(Type type)
        {
            this.type = type;
        }
    
        @Override
        public ComponentScope getScope()
        {
            return ComponentScope.Undefined;
        }
    
        @Override
        public Injectable<Model> getInjectable(ComponentContext ic, ModelParam mp, Type type)
        {
            if (type instanceof Class && Model.class.isAssignableFrom((Class<?>) type))
            {
                return new ModelInjectableProvider(type);
            }
    
            return null;
        }
    
        @Override
        public Model getValue(HttpContext ctx)
        {
            if (type instanceof Class && Model.class.isAssignableFrom((Class<?>) type))
            {
                HttpRequestContext request = ctx.getRequest();
    
                Model model = null;
    
                if (HttpMethod.POST.equals(request.getMethod()) || HttpMethod.PUT.equals(request.getMethod()))
                {
                    model = (Model) MyGuiceInjector.inject((Class<?>) type);
    
                    if (model != null)
                        model = request.getEntity(model.getClass());
                }
    
                return model;
            }
    
            return null;
        }
    }
    

, - .

,

+1

All Articles