[英]Unmarshalling XML or JSON to guice injected object in jersey using @InjectParam annotation
我有一個問題,正確地解組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 = []]
奇怪的是,當我用默認類替換接口參數(@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-INF進行標准路由,但這是我的代碼注冊了jersey組件(當然,如果你仍然希望看到我的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>
在我在澤西島郵件列表中得到回復后說,球衣沒有支持guice,我已經進一步嘗試並想出一個解決方案。 這是消息:
“Jersey 2.0不支持Guice。請參閱https://java.net/jira/browse/JERSEY-1950 ”。 ( http://jersey.576304.n2.nabble.com/Guice-integration-td7581958.html )
為了完整起見,我也會在這里發布解決方案。 我提出的解決方案可能不是每個人的通用解決方案,但如果滿足以下條件,可能會給出一些想法或幫助:
在我的特定情況下,我的所有bean都標有@Model注釋並實現我的“模型”界面。 其他類,例如存儲庫或服務,無論如何都可以通過guice正常注入到澤西資源中。 我遇到的問題僅僅是與@InjectParam注釋有關。
我認為它的神奇之處主要在於:
model = request.getEntity(model.getClass());"
它通過反序列化的內容(無論是JSON還是XML)神奇地填充guice注入對象。 我很驚訝在使用@InjectParam時內置解決方案不會發生這種情況,因為畢竟實際注入不是問題 - 它只是沒有填充對象。
所以這就是我如何解決它:
創建了一個名為“ModelParam”的注釋:
@Target({ PARAMETER, METHOD, FIELD }) @Retention(RUNTIME) @Documented public @interface ModelParam { }
使用新的“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); }
為新的“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; } }
希望這可以幫助有類似問題的人。
最好的問候,邁克爾
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.