我在资源类中创建了一个情境,我收到了所有3个端点的404,并希望有人可以帮助解释原因。这是我的资源类:
@Path("/incidents")
public class RegistrationResource {
@GET
@Path("/{incidentId}/registration")
public Response getRegisteredIncidents(@PathParam("incidentId") String incidentId) {
...
}
@GET
@Path("/registration/download")
public Response downloadRegistrationIncidentsReport() {
...
}
@GET
@Path("/registration/email")
public Response emailRegistrationIncidentsReport() {
...
}
}
我还使用JAX-RS Application类来注册我的资源并设置基础"上下文"所有端点的路径:
@ApplicationPath("/context")
public class AdminApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet<Class<?>>();
resources.add(RegistrationResource.class);
...
return resources;
}
}
现在,如果我将这些方法拆分为多个资源类,我可以让每个服务都能正常工作,但我的问题是为什么上面的设计不会起作用?我按照上述方法的顺序尝试调用的完整端点是:
/context/incidents/55/registration
/context/incidents/registration/download
/context/incidents/registration/email
为什么找不到上面的映射?通过这种设计,我为每个端点获得了404.
org.apache.wink.server.internal.RequestProcessor logException在调用处理程序链期间发生以下错误:WebApplicationException(404 - Not Found),消息&#39; null&#39;处理发送到http://localhost:9081/someapp/context/incidents/55/registration
的GET请求时
作为进一步的澄清点,我使用Wink 1.1作为我的JAX-RS实现,因为我此时已经绑定到WebSphere 8.5.5.5附带的打包版本。
谢谢你的时间!
-----------更新#1 -----------
根据以下评论,我修改了一些端点。但是,我仍然在某些端点上收到随机故障404或者有趣的是405错误。重要的是要注意,如果我重新部署,有时不同的端点会失败,或者也许一切都会起作用。然后,如果我再次重新部署,我会得到类似的,但某些端点的不同结果失败或全部工作。底线是它非常不一致。
因此,似乎有更多的端点与我原来的帖子相冲突,所以为了完整起见,我在这里粘贴所有端点。
/* Public Service Set */
@ApplicationPath("/public")
public class PublicApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet<Class<?>>();
resources.add(IncidentResource.class);
resources.add(IncidentDetailsResource.class);
resources.add(TicketResource.class);
resources.add(RegistrationResource.class);
return resources;
}
}
@Path("/incidents")
public class IncidentResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getIncidents() throws Exception {
//...
}
@Path("/")
public class IncidentDetailsResource {
@GET
@Path("/v1/incidents/{incidentId}/details")
@Produces(MediaType.APPLICATION_JSON)
public Response getIncidentDetails(@PathParam("incidentId") String incidentId) throws Exception {
//...
}
@GET
@Path("/v2/incidents/{incidentId}/details")
@Produces(MediaType.APPLICATION_JSON)
public Response getIncidentDetailsAsJson(@PathParam("incidentId") String incidentId) throws Exception {
//...
}
}
@Path("/incidents/{incidentId}/tickets")
public class TicketResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getTickets(@PathParam("incidentId") String incidentId) throws Exception {
//...
}
}
@Path("/incidents")
public class RegistrationResource {
@POST
@Path("/{incidentId}/registration")
@Consumes(MediaType.APPLICATION_JSON)
public Response register(@PathParam("incidentId") String incidentId, BaseRequestMessage<IncidentRegistrationRequest> baseRequestMessage) throws Exception {
//...
}
}
/* Admin Service Set */
@ApplicationPath("/admin")
public class AdminApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet<Class<?>>();
resources.add(AdminIncidentResource.class);
resources.add(AdminIncidentDetailsResource.class);
resources.add(AdminRegistrationResource.class);
resources.add(AdminRegistrationReportResource.class);
resources.add(AdminTicketResource.class);
return resources;
}
}
@Path("/incidents")
public class AdminIncidentResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response addIncident(BaseRequestMessage<IncidentRequest> baseRequestMessage) throws Exception {
//...
}
@PUT
@Path("/{incidentId}")
@Produces(MediaType.APPLICATION_JSON)
public Response updateIncident(@PathParam("incidentId") String incidentId, BaseRequestMessage<IncidentRequest> baseRequestMessage) throws Exception {
//...
}
@DELETE
@Path("/{incidentId}")
@Produces(MediaType.APPLICATION_JSON)
public Response deleteIncident(@PathParam("incidentId") String incidentId) throws Exception {
//...
}
}
@Path("/")
public class AdminIncidentDetailsResource {
@PUT
@Path("/v1/incidents/{incidentId}/details")
@Consumes(MediaType.APPLICATION_JSON)
public Response updateIncidentDetails(@PathParam("incidentId") String incidentId, BaseRequestMessage<IncidentDetailRequest> baseRequestMessage) throws Exception {
//...
}
@PUT
@Path("/v2/incidents/{incidentId}/details")
@Consumes(MediaType.APPLICATION_JSON)
public Response updateIncidentDetailsAsJson(@PathParam("incidentId") String incidentId, BaseRequestMessage<JsonNode> baseRequestMessage) throws Exception {
//...
}
}
@Path("/incidents/{incidentId}/tickets")
public class AdminTicketResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response addTicket(@PathParam("incidentId") String incidentId, BaseRequestMessage<TicketRequest> baseRequestMessage) throws Exception {
//...
}
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public Response updateTicket(@PathParam("incidentId") String incidentId, BaseRequestMessage<TicketRequest> baseRequestMessage) throws Exception {
//...
}
@DELETE
@Path("/{detailsUrn}")
@Consumes(MediaType.APPLICATION_JSON)
public Response removeTicket(@PathParam("incidentId") String incidentId, @PathParam("detailsUrn") String detailsUrn) throws Exception {
//...
}
}
@Path("/incidents/registration/report")
public class AdminRegistrationReportResource {
@GET
@Path("/download")
@Produces("application/vnd.ms-excel")
public Response downloadRegistrationReport() throws Exception {
//...
}
@GET
@Path("/email")
@Produces(MediaType.APPLICATION_JSON)
public Response emailRegistrationReport() throws Exception {
//...
}
}
@Path("/incidents/{incidentId}/registration")
public class AdminRegistrationResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getRegisteredUsers(@PathParam("incidentId") String incidentId) throws Exception {
//...
}
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public Response updateRegisteredUser(@PathParam("incidentId") String incidentId, BaseRequestMessage<IncidentRegistrationRequest> baseRequestMessage) throws Exception {
//...
}
}
为了方便起见......上面的代码最终产生了这些uris:
POST / public / incidents / {incidentId} / registration
POST / admin / events
这是很多代码;我本来想避免这种情况,但似乎有必要。而且,为了它的价值,在我添加AdminRegistrationResource
类之前,事情似乎正在发挥作用。也许某个端点中的一个端点开始引发冲突?
再次......感谢您的时间!
-----------更新#2 -----------
我认为我在这里发布了我最近的一个特定错误,希望它可能有助于解决问题。当我打电话给这个终点时:
获取/公开/事件
我收到此错误消息:
00000203 ResourceRegis I org.apache.wink.server.internal.registry.ResourceRegistry filterDispatchMethods The system cannot find any method in the com.somewhere.unimportant.rest.resource.external.RegistrationResource class that supports GET. Verify that a method exists.
00000203 RequestProces I org.apache.wink.server.internal.RequestProcessor logException The following error occurred during the invocation of the handlers chain: WebApplicationException (405) with message 'null' while processing GET request sent to https://test.somewhere.com:88888/app777/public/events
现在更有趣的是,我在本地收到此错误,但我也将我的代码推送到有两个负载均衡服务器的测试环境。在测试环境中,我在其中一个服务器上始终收到此错误,但另一个一致地工作。因此,在一个成功的服务器和一个不成功的服务器上分离50%的故障率。
奇怪......为什么它会在那个类中查找我正在点击的端点?
-----------更新#3 -----------
好的,我已经完全在我的PublicApplication类中使用了@ApplicationPath注释(如下面的评论中所建议的),并将其替换为仅仅#34; /&#34;但在以下情况下仍然会收到404错误(请注意,对于此测试,我已完全删除了&#34; admin&#34;服务):
/* Public (and only) Service Set */
@ApplicationPath("/")
public class PublicApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet<Class<?>>();
resources.add(IncidentResource.class);
resources.add(IncidentDetailsResource.class);
resources.add(TicketResource.class);
resources.add(RegistrationResource.class);
return resources;
}
}
@Path("/public")
public class IncidentResource {
@GET
@Path("/incidents")
@Produces(MediaType.APPLICATION_JSON)
public Response getIncidents() throws Exception {
//...
}
@Path("/public")
public class IncidentDetailsResource {
@GET
@Path("/v1/incidents/{incidentId}/details")
@Produces(MediaType.APPLICATION_JSON)
public Response getIncidentDetails(@PathParam("incidentId") String incidentId) throws Exception {
//...
}
@GET
@Path("/v2/incidents/{incidentId}/details")
@Produces(MediaType.APPLICATION_JSON)
public Response getIncidentDetailsAsJson(@PathParam("incidentId") String incidentId) throws Exception {
//...
}
}
@Path("/public/incidents/{incidentId}/tickets")
public class TicketResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getTickets(@PathParam("incidentId") String incidentId) throws Exception {
//...
}
}
@Path("/public/incidents/{incidentId}/registration")
public class RegistrationResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response register(@PathParam("incidentId") String incidentId, BaseRequestMessage<IncidentRegistrationRequest> baseRequestMessage) throws Exception {
//...
}
}
在这种情况下,我收到此错误:
org.apache.wink.server.internal.RequestProcessor logException The following error occurred during the invocation of the handlers chain: WebApplicationException (404 - Not Found) with message 'null' while processing GET request sent to http://test.somewhere.com:88888/app777/public/events
试图打电话时:
获取/公开/事件
上述其他4个端点也可以正常工作。并且,更重要的是,如果我将IncidentResource类更改为如下所示(将方法级别的@Path注释完全移至类级别),则所有 5个端点工作:
@Path("/public/incidents")
public class IncidentResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getIncidents() throws Exception {
//...
}
我感谢所有与我同住的人!
答案 0 :(得分:2)
删除@ApplicationPath(“/ context”)或者不要在请求uri中使用/ context,或者只使用@ApplicationPath(“/”)它甚至在升级时都不会中断。
以上所有不同的方法都应该有效,但对于您的版本,我会建议使用@ApplicationPath(“/”)并通过删除/上下文来更新您的请求uris,并且所有内容都应该按照您最初的预期方式工作。
Apache Wink目前尚不支持ApplicationPath。
答案 1 :(得分:0)
这可能对您有用:
@Path("/incidents/{incidentId}/registration")
public class RegistrationResource1 {
@GET
public Response getRegisteredIncidents(@PathParam("incidentId") String incidentId) {
...
}
}
@Path("/incidents/registration/download")
public class RegistrationResource {
@GET
public Response downloadRegistrationIncidentsReport() {
...
}
}
但是,我不建议像那样拆分控制器。相反,只需要在每个函数中删除尽可能多的代码来分离业务逻辑类。