解组XML或JSON以使用@InjectParam注释来训练球衣中的注入对象

时间:2014-02-22 10:15:57

标签: java jersey guice

我遇到了正确解组XML数据的问题。我正在使用guice和jersey技术。奇怪的是 是当我尝试使用JAXB手动解组时,一切正常:

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()));

我最终得到了正确填充的对象: DefaultRole [id = null,name = [{val = Administrator},{l = en,val = Administrator}],permissions = [READ_XX,WRITE_XX]]

然而,当使用jersey并注入我的Role界面时,它不起作用:

@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;
}

对象已实例化,但未填充: DefaultRole [id = null,name = null,permissions = []]

奇怪的是,当我用默认类替换interface参数(@InjectParam Role role)时:

@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;
}

它有效,我再次正确填充了我的对象。

使用界面使用guice注入对象时,我需要做什么才能正确填充对象?

我的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>

1 个答案:

答案 0 :(得分:1)

在我在球衣邮件列表中得到回复后说,球衣不支持guice,我已经进一步尝试并提出解决方案。以下是信息:

“Jersey 2.0不支持Guice。请参阅https://java.net/jira/browse/JERSEY-1950”。 (http://jersey.576304.n2.nabble.com/Guice-integration-td7581958.html

为了完整起见,我也会在这里发布解决方案。我提出的解决方案可能不是每个人的通用解决方案,但如果满足以下条件,可能会给出一些想法或帮助:

  1. 所有要注入的对象都使用类级别注释进行“标记”。
  2. 所有要注入的对象都实现了一些接口(虽然它可以在不指定Object的情况下工作吗?)。
  3. 您很高兴创建自己的自定义参数注释。
  4. 在我的特定情况下,我的所有bean都标有@Model注释并实现我的“Model”界面。其他类,例如存储库或服务,无论如何都可以通过guice正常注入到泽西资源中。我遇到的问题仅仅是与@InjectParam注释有关。

    我认为它的神奇之处主要在于:

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

    使用反序列化的内容(无论是JSON还是XML)神奇地填充guice-inject-object。我很惊讶在使用@InjectParam时内置解决方案不会发生这种情况,因为毕竟实际注入不是问题 - 它只是没有填充对象。

    所以这就是我解决它的方法:

    1. 创建了一个名为“ModelParam”的注释:

      @Target({ PARAMETER, METHOD, FIELD })
      @Retention(RUNTIME)
      @Documented
      public @interface ModelParam
      {
      }
      
    2. 使用新的“ModelParam”注释替换了我的资源“RoleRestWS”中的“InjectParam”注释:

      @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);
      }
      
    3. 为新的“ModelParam”注释创建了一个InjectableProvider:

      @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;
          }
      }
      
    4. 希望这有助于遇到类似问题的人。

      祝你好运, 迈克尔