我想在REST端点上接受JSON并将其转换为正确的类型以立即进行验证.
端点如下所示:
@POST
public Response createCar(@Valid Car car) {
// persist to DB
// ...
}
Run Code Online (Sandbox Code Playgroud)
但是Car有很多子类,例如Van,SelfDrivingCar,RaceCar等.我怎样才能接受端点上不同的JSON表示,同时保持资源中的验证代码简洁如下@Valid Car car?
再说一遍:我发送JSON就像(这里,它是Car的子类的表示,即SelfDrivingCar):
{
"id" : "t1", // every Car has an Id
"kind" : "selfdriving", // every Car has a type-hint
"max_speed" : "200 mph", // some attribute
"ai_provider" : "fastcarsai ltd." // this is SelfDrivingCar-specific
}
Run Code Online (Sandbox Code Playgroud)
我希望验证机制查看kind属性,创建适当子类的实例,例如SelfDrivingCar执行验证.
我知道我可以为所有类型的汽车创建不同的端点,但那似乎并不干净.而且我知道我可以使用真实Validator而不是注释并手工完成,所以我只是问这个问题是否有一些优雅的捷径.
我有一个REST API的以下堆栈
我的目标是在发生错误时拥有自定义响应主体.我希望能够向客户端发送一个解释,以便更容易调试.
首先我尝试使用@Context HttpServletResponse并在那里设置http状态代码,但是被泽西忽略了(这是正常的行为,但这超出了我的理解)
然后我试着这样使用WebApplicationException:
@GET
@Path("/myapi")
public BaseResponse getSomething() {
BaseResponse b = new BaseResponse();
if(error) {
b.setStatusDescription("reason for error");
throw new WebApplicationException(Response.status(Response.Status.CONFLICT).entity(b).build());
}
//add content to BaseReponse
return b
}
Run Code Online (Sandbox Code Playgroud)
但是Tomcat给我的回报是这样的:
<html>
<head>
<title>Apache Tomcat/7.0.47 - Error report</title>
<style>
<!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22p
Run Code Online (Sandbox Code Playgroud)
哪个标准的Tomcat html输出受到我想要返回的响应体的上下文长度的限制(.entity(b)- 长度b).所以它被认可,但Tomcat只是用自己的错误页面覆盖它.
作为旁注,我也尝试以相同的结果返回响应:
return Response.status(Response.Status.CONFLICT).entity(b).build()
Run Code Online (Sandbox Code Playgroud)
那么我如何告诉Tomcat让我一个人让自己的回答通过?
我不明白为什么javax.ws.rs.Produces可以使用两种以上的媒体类型.据我所知,Web服务客户端必须确切知道Web服务返回的媒体类型是什么.我在http://docs.oracle.com/javaee/6/api/javax/ws/rs/Produces.html查看了它的API,但我找不到答案.有人有什么想法吗?谢谢.
根据这篇文章(http://restcookbook.com/HTTP%20Methods/put-vs-post/),PUT应该作为更新资源的方法.
但是,使用JAX_RS 2.0和Jersey 2.0练习RESTful,我认为它不会更新特定资源.(即我正在使用JAX_RS 2.0和Jersey 2.0学习RESTful)
这是一个这样的资源.
<customer>
<name>Before</name>
<postcode>111</postcode>
</customer>
Run Code Online (Sandbox Code Playgroud)
我想要做的是更新(也许我应该说"替换")这个资源.
ClientConfig config = new ClientConfig();
Client client = ClientBuilder.newClient(config);
WebTarget target = client.target("http://xxx/yyy/zzz/end.cust");
Customer cust = new Customer();
cust.setName("After");
cust.setPostcode(222);
target.path("Before").request().put(Entity.xml(cust));
Run Code Online (Sandbox Code Playgroud)
@Id注释在"Customer"类中设置为"Name",因此路径"Before"应该作为ID工作,第一个资源(名为"Before")应该替换为第二个资源(名为"After") ").
但是,在执行上面的编码之后,"之前"资源仍然存在,并且有一个新的"After"resrouce.似乎PUT方法可以创建一个新资源,而不是更新某些东西.(即有"之前"和"之后"资源,并且没有更新任何内容)
我测试了一个POST方法以创建一个新资源,并按照我的预期创建了一个新资源.
如果你看到我做错了什么或需要做什么,你能提出一些建议吗?
编辑
我将添加服务器端代码.用@PUT注释的方法是这样的.
@PUT
@Path("{id}")
@Consumes({"application/xml", "application/json"})
public void edit(@PathParam("id") String id, Customer entity) {
super.edit(entity);
}
Run Code Online (Sandbox Code Playgroud)
这是在一个名为CustomerFacadeREST.java的类中,在我创建"来自数据库的RESTful服务"后自动创建.
根据NetBeans的文档,super.edit()方法最初是这样的.
public void edit(T entity) {
getEntityManager().merge(entity);
}
Run Code Online (Sandbox Code Playgroud)
在"Customer"类中,@ Id以这种方式设置为"name"值.
public class Customer implements Serializable {
private static final long serialVersionUID = 1L; …Run Code Online (Sandbox Code Playgroud) 我正在使用Jersey / JAX-RS来实现RESTful Web服务。我对ExceptionMapper接口有疑问,似乎在任何地方都没有记录。
假设我有以下自定义(extend RuntimeException)异常:
FizzException extends RuntimeExceptionBuzzException extends FizzException现在,让我们说我的异常映射器执行以下Exception到Response映射的映射:
FizzException 实际上映射到未找到的HTTP 404BuzzException 映射到HTTP 403 UNAUTHORIZED因此,如果我正确理解API,则需要实现3个不同的异常映射器:
@Provider
public class DefaultExceptionMapper implements ExceptionMapper<Exception> {
@Override
Response toResponse(Exception exc) {
// Map to HTTP 500
}
}
@Provider
public class FizzExceptionMapper implements ExceptionMapper<FizzException> {
@Override
Response toResponse(Exception exc) {
// Map to HTTP 404
}
}
@Provider
public class BuzzExceptionMapper implements ExceptionMapper<BuzzException> {
@Override
Response toResponse(Exception exc) …Run Code Online (Sandbox Code Playgroud) 我已经读过java EE6中的web.xml是可选的.所以没有web.xml,我如何告诉应用服务器使用Jersey作为JAX-RS规范的实现?
这与jax-rs-2-0-change-default-implementation有关, 我有一个OSGi包,它包含cxf 2.7.8和openejb.cxf依赖项作为嵌入式依赖项添加.
当我尝试部署webapp时,我得到以下异常.当我在启动服务器时设置系统属性,因为-Djavax.ws.rs.ext.RuntimeDelegate=org.apache.cxf.jaxrs.impl.RuntimeDelegateImpl这可以解决.
但是在上面的链接中它说当我有META-INF/services/javax.ws.rs.ext.RuntimeDelegate文件的内容,因为org.apache.cxf.jaxrs.impl.RuntimeDelegateImpl这可以解决.
在我的OSGi包中,该文件存在于cxf-rt-frontend-jaxrs-2.7.8.jar但是这个jar嵌入在OSGi包中似乎没有得到正确的选择.我试图将相同的文件添加到OSGi包中,META-INF/services但它也不起作用.
有人可以告诉我有没有办法摆脱这个没有手动设置系统属性?
java.lang.Class.forName0(本机方法)的java.lang.ExceptionInInitializerError,位于com.sun.proxy的java.lang.Class.forName(Class.java:191).$ Proxy89.(未知来源)at sun.reflect位于sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)的sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)中的.NativeConstructorAccessorImpl.newInstance0(Native Method)at java.lang.reflect.Constructor.newInstance(Constructor) .java:526)在java.lang.reflect.Proxy.newInstance(Proxy.java:764)的java.lang.reflect.Proxy.newProxyInstance(Proxy.java:755)atg.apache.openejb.server.cxf. rs.CxfRSService $ ContextBean.(CxfRSService.java:192)位于org.apache.openejb.server.cxf.rs.CxfRSService的org.apache.openejb.server.cxf.rs.CxfRSService.contextCDIIntegration(CxfRSService.java:111) .integrateCDIAndJaxRsInjections(CxfRSService.java:100)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccess orImpl.invoke(NativeMethodAccessorImpl.java:57)位于org.apache.openejb.observer的java.lang.reflect.Method.invoke(Method.java:606)的sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) .ObserverManager $ MethodInvocation.invoke(ObserverManager.java:400)org.apache.openejb.observer.ObserverManager.doFire(ObserverManager.java:111)at org.apache.openejb.observer.ObserverManager.fireEvent(ObserverManager.java:100 )org.apache.openejb.loader.SystemInstance.fireEvent(SystemInstance.java:134)atg.apache.openejb.cdi.ThreadSingletonServiceImpl.initialize(ThreadSingletonServiceImpl.java:150)org.apache.openejb.cdi.CdiBuilder.在org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:838)的org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:644)中构建(CdiBuilder.java:41) at org.apache.tomee.catalina.TomcatWebAppBuilder.startInternal(TomcatWebAppBuilder.java:1250)at sun.reflect.NativeMethodAccessorImp l.invoke0(本机方法)在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)在java.lang.reflect.Method.invoke(方法. java:606)org.wso2.carbon.javaee.tomee.ASTomcatWebAppBuilder.configureStart(ASTomcatWebAppBuilder.java:127)org.apache.tomee.catalina.GlobalListenerSupport.lifecycleEvent(GlobalListenerSupport.java:130)at org.wso2.carbon .javaee.tomee.ASGlobalListenerSupport.lifecycleEvent(ASGlobalListenerSupport.java:74)在org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)在org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java :90)org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5412)org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)org.apache.catalina.core.在org.apache.catalina.core.Contain的ContainerBase.addChildInternal(ContainerBase.java:901)ergase.addChild(ContainerBase.java:877)org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)org.wso2.carbon.tomcat.internal.CarbonTomcat.addWebApp(CarbonTomcat.java:345)在org.wso2.carbon.tomcat.internal.CarbonTomcat.addWebApp(CarbonTomcat.java:190)在org.wso2.carbon.webapp.mgt.TomcatGenericWebappsDeployer.handleWebappDeployment(TomcatGenericWebappsDeployer.java:257)在org.wso2.carbon.webapp .mgt.TomcatGenericWebappsDeployer.handleWarWebappDeployment(TomcatGenericWebappsDeployer.java:207)org.wso2.carbon.webapp.mgt.TomcatGenericWebappsDeployer.handleHotDeployment(TomcatGenericWebappsDeployer.java:174)org.wso2.carbon.webapp.mgt.TomcatGenericWebappsDeployer.deploy(TomcatGenericWebappsDeployer) .java:139)org.wso2.carbon.webapp.mgt.AbstractWebappDeployer.deployThisWebApp(AbstractWebappDeployer.java:204)org.wso2.carbon.webapp.mgt.AbstractWebappDeployer.deploy(AbstractWebappDeployer.java:111)at org. wso2.carbon.webapp.deployer.WebappDeployer.deploy(WEBA ppDeployer.java:42)org.apache.axis2.deployment.repository.util.DeploymentFileData.deploy(DeploymentFileData.java:136)org.apache.axis2.deployment.DeploymentEngine.doDeploy(DeploymentEngine.java:807)at org位于org.apache.axis2.deployment.RepositoryListener的org.apache.axis2.deployment.RepositoryListener.update(RepositoryListener.java:377)上的.apache.axis2.deployment.repository.util.WSInfoList.update(WSInfoList.java:144) .checkServices(RepositoryListener.java:254)org.apache.axis2.deployment.DeploymentEngine.loadServices(DeploymentEngine.java:135)org.wso2.carbon.core.CarbonAxisConfigurator.deployServices(CarbonAxisConfigurator.java:567)org.位于org.wso2.carbon.core.internal的org.wso2.carbon.core.internal.CarbonCoreServiceComponent.notifyBefore(CarbonCoreServiceComponent.java:235)中的wso2.carbon.core.internal.DeploymentServerStartupObserver.completingServerStartup(DeploymentServerStartupObserver.java:51). StartupFinalizerServiceComponent.completeInitialization(StartupFinalizerS erviceComponent.java:185)在org.wso2.carbon.core.internal.StartupFinalizerServiceComponent.serviceChanged(StartupFinalizerServiceComponent.java:288)在org.eclipse.osgi.internal.serviceregistry.FilteredServiceListener.serviceChanged(FilteredServiceListener.java:107)在组织位于org.eclipse.osgi.framework的org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)的.eclipse.osgi.framework.internal.core.BundleContextImpl.dispatchEvent(BundleContextImpl.java:861) .eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148)在org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEventPrivileged(ServiceRegistry.java:819)在org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEvent(ServiceRegistry .java:771)org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.register(ServiceRegistrationImpl.java:130)org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.registerService(ServiceRegistry.java:214))org.eclipse.osgi.framework.internal.core.BundleContextImpl.registerService(BundleContextImpl.java:433)at org.eclipse.osgi.framework.internal.core.BundleContextImpl.registerService(BundleContextImpl.java:451)at org.位于sun.reflect.NativeMethodAccessorImpl的org.wso2.carbon.throttling.agent.internal.ThrottlingAgentServiceComponent.activate(ThrottlingAgentServiceComponent.java:100)中的wso2.carbon.throttling.agent.internal.ThrottlingAgentServiceComponent.registerThrottlingAgent(ThrottlingAgentServiceComponent.java:123).在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)的sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)的java.lang.reflect.Method.invoke上的invoke0(Native Method)(Method.java: 606)org.eclipse.equinox.internal.ds.model.ServiceComponent.activate(ServiceComponent.java:260)org.eclipse.equinox.internal.ds.model.ServiceComponentProp.activate(ServiceComponentProp.java:146)at org .eclipse.equinox.internal.ds 位于org.eclipse.equinox.internal.ds.InstanceProcess.build上的orm.eclipse.equinox.internal.ds.InstanceProcess.buildComponent(InstanceProcess.java:620)中的.model.ServiceComponentProp.build(ServiceComponentProp.java:345),InstanceProcessnts .java:197)org.eclipse.equinox.internal.ds.Resolver.getEligible(Resolver.java:343)org.eclipse.equinox.internal.ds.SCRManager.serviceChanged(SCRManager.java:222)at org. eclipse.osgi.internal.serviceregistry.FilteredServiceListener.serviceChanged(FilteredServiceListener.java:107)位于org.eclipse.osgi.framework的org.eclipse.osgi.framework.internal.core.BundleContextImpl.dispatchEvent(BundleContextImpl.java:861). eventmgr.EventManager.dispatchEvent(EventManager.java:230)位于org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEventPrivileged(ServiceRegistry)的org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148). java:819)at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.pu blishServiceEvent(ServiceRegistry.java:771)位于org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.registerService(ServiceRegistry.java:214 org.eclipse.osgi.framework.internal.core.BundleContextImpl.registerService(BundleContextImpl.java:433)位于org.wso2的org.eclipse.osgi.framework.internal.core.BundleContextImpl.registerService(BundleContextImpl.java:451)位于org.wso2.carbon.cron.internal.CarbonCoreServiceComponent的org.wso2.carbon.core.init.CarbonServerManager.start(CarbonServerManager.java:219)上的.carbon.core.init.CarbonServerManager.initializeCarbon(CarbonServerManager.java:517) .activate(CarbonCoreServiceComponent.java:91)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43 )在java.la 位于org.eclipse.equinox.internal.ds.model的org.eclipse.equinox.internal.ds.model.ServiceComponent.activate(ServiceComponent.java:260)的ng.reflect.Method.invoke(Method.java:606). ServiceComponentProp.activate(ServiceComponentProp.java:146)atg.eclipse.equinox.internal.ds.model.ServiceComponentProp.build(ServiceComponentProp.java:345)at org.eclipse.equinox.internal.ds.InstanceProcess.buildComponent(InstanceProcess. …
我使用JAX-RS实现了Rest Web服务(该功能不相关).现在我想使用Swagger生成其文档.我已按照以下步骤操作:
1)在build.gradle我得到我需要的所有依赖项:
compile 'org.glassfish.jersey.media:jersey-media-moxy:2.13'
2)我用Swagger注释记录我的代码
3)我在我的Application子类中连接了Swagger:
public class ApplicationConfig extends ResourceConfig {
/**
* Main constructor
* @param addressBook a provided address book
*/
public ApplicationConfig(final AddressBook addressBook) {
register(AddressBookService.class);
register(MOXyJsonProvider.class);
register(new AbstractBinder() {
@Override
protected void configure() {
bind(addressBook).to(AddressBook.class);
}
});
register(io.swagger.jaxrs.listing.ApiListingResource.class);
register(io.swagger.jaxrs.listing.SwaggerSerializers.class);
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.2");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8282");
beanConfig.setBasePath("/");
beanConfig.setResourcePackage("rest.addressbook");
beanConfig.setScan(true);
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我进入我的服务时http://localhost:8282/swagger.json,我得到了这个输出.
你可以在这里查看我的公共回购.
我是java rest应用程序的新手.我正在尝试运行一个应用程序,但我有这个例外
message com.sun.jersey.api.client.ClientHandlerException: A message body writer for Java type, class java.util.ArrayList, and MIME media type, multipart/form-data, was not found
exception
com.sun.jersey.api.client.ClientHandlerException: com.sun.jersey.api.client.ClientHandlerException: A message body writer for Java type, class java.util.ArrayList, and MIME media type, multipart/form-data, was not found
com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:155)
com.sun.jersey.api.client.Client.handle(Client.java:652)
com.sun.jersey.api.client.WebResource.handle(WebResource.java:682)
com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:570)
org.eu.paas.client.APIClient.doPost(APIClient.java:265)
javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
Run Code Online (Sandbox Code Playgroud)
在APIClient.java:265我有一些事情:
cr = service.path(path)
.type(MediaType.MULTIPART_FORM_DATA)
.post(ClientResponse.class, listForm);
Run Code Online (Sandbox Code Playgroud)
哪里listForm是ArrayList<InputStream>
在其余的申请中,我有:
@POST
@Path("{appId-appId}/action/Multideploy/env/{envId-envId}")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_XML)
Response MultideployApplication(
@PathParam("appId-appId") String appid, @PathParam("envId-envId") String envid,
@FormDataParam("file") List<InputStream> uploadedInputStream);
Run Code Online (Sandbox Code Playgroud)
同样在我的pom.xml中,我有这些依赖项: …
我有这样的URI:
java.net.URI location = UriBuilder.fromPath("../#/Login").queryParam("token", token).build();
我发送它作为回应: return Response.seeOther(location).build()
但是,在上面的URI中,#正在编码%23/.如何在不对哈希进行编码的情况下创建URI #.根据官方文件,fragment()必须使用一种方法来保持未编码.
URI的大多数组件都允许使用URI模板,但它们的值仅限于特定组件.例如
.UriBuilder.fromPath( "{ARG1}")建立( "富#栏"); 将导致'#'的编码,使得结果URI为"foo%23bar".要创建URI"foo #bar",请使用UriBuilder.fromPath("{arg1}").fragment("{arg2}").build("foo","bar").
从文档中查看示例,我不确定如何在我的案例中应用它.
最终的URI应如下所示:
http://localhost:7070/RTH_Sample14/#Login?token=eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczpcL1wvcnRoLmNvbSIsInN1YiI6IlJUSCIsInJvbGUiOiJVU0VSIiwiZXhwIjoxNDU2Mzk4MTk1LCJlbWFpbCI6Imtpcml0aS5rOTk5QGdtYWlsLmNvbSJ9.H3d-8sy1N-VwP5VvFl1q3nhltA-htPI4ilKXuuLhprxMfIx2AmZZqfVRUPR_tTovDEbD8Gd1alIXQBA-qxPBcxR9VHLsGmTIWUAbxbyrtHMzlU51nzuhb7-jXQUVIcL3OLu9Gcssr2oRq9jTHWV2YO7eRfPmHHmxzdERtgtp348
jax-rs ×10
java ×9
rest ×6
java-ee ×2
jersey ×2
jersey-2.0 ×2
web-services ×2
cxf ×1
dropwizard ×1
grizzly ×1
http-method ×1
json ×1
maven ×1
osgi ×1
put ×1
swagger ×1
tomcat7 ×1
uribuilder ×1
validation ×1