【发布时间】:2016-09-27 14:34:14
【问题描述】:
我在 Resource 类中创建了一种情况,在该情况下,我收到所有 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) with message 'null' while processing GET request sent to http://localhost:9081/someapp/context/incidents/55/registration
作为进一步的说明,我使用 Wink 1.1 作为我的 JAX-RS 实现,因为此时我绑定到 WebSphere 8.5.5.5 附带的打包版本。
感谢您的宝贵时间!
------------更新#1-----------
根据下面的 cmets,我修改了一些端点。但是,我仍然在某些端点上收到随机故障,出现 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 {
//...
}
}
为方便起见...上面的代码最终生成了这些 uri:
- GET /public/incidents
- GET /public/v1/incidents/{incidentId}/details
- GET /public/v2/incidents/{incidentId}/details
- GET /public/incidents/{incidentId}/tickets
POST /public/incidents/{incidentId}/registration
POST /admin/incidents
- PUT /admin/incidents/{incidentId}
- 删除 /admin/incidents/{incidentId}
- PUT /admin/v1/incidents/{incidentId}/details
- PUT /admin/v2/incidents/{incidentId}/details
- POST /admin/incidents/{incidentId}/tickets
- PUT /admin/incidents/{incidentId}/tickets
- 删除 /admin/incidents/{incidentId}/tickets/{detailsUrn}
- GET /admin/incidents/registration/report/download
- GET /admin/incidents/registration/report/email
- GET /admin/incidents/{incidentId}/registration
- PUT /admin/incidents/{incidentId}/registration
代码很多;我本来想避免这种情况,但似乎有必要。此外,就其价值而言,在我添加 AdminRegistrationResource 类之前,一切似乎都在发挥作用。也许该类中某个端点的某些东西开始引起冲突?
再次...感谢您的宝贵时间!
------------更新#2-----------
我想我会在这里发布我最近的一个具体错误,希望它可以帮助解决问题。当我调用这个端点时:
GET /public/事件
我收到此错误消息:
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 注释(如下面的 cmets 所建议的)并将其替换为仅仅“/”,但在以下情况下仍会收到 404 错误(请注意,对于此测试,我已完全删除“管理”服务):
/* 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
尝试调用时:
GET /public/事件
上面的其他 4 个端点也可以正常工作。而且,更重要的是,如果我将 IncidentResource 类更改为如下所示(将方法级别的 @Path 注释完全移动到类级别),那么 所有 5 个端点工作:
@Path("/public/incidents")
public class IncidentResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getIncidents() throws Exception {
//...
}
感谢所有陪伴我至今的人!
【问题讨论】:
-
好主意。最初我 not 有斜线并添加它们,希望它们会有所帮助。但是,我确实按照您的建议再次删除了它们,但没有任何区别。
-
@Roman Vottner:在 JAX-RS Application 类的扩展中;我已经编辑了我的问题以包含上述内容。
-
我希望这也能奏效。我肯定有一个 WebSphere 服务,在不同的路径上有两个不同的
@GET方法,尽管我的两个方法都没有参数。您是否尝试过一些不同的路径/参数组合,只是为了尝试隔离特定原因?另外,什么版本的 WebSphere?您是否查看了 WebSphere 日志以了解启动时和收到请求时的错误消息? -
我有多种方法组合与其他路径/参数组合,这些都很好。启动时没有 WebSphere 错误,并且 WebSphere 的确切版本是 8.5.5.5。我也用收到的实际错误消息修改了原始问题。
-
我只是在抓紧尝试的事情,在这里找出根本原因...我让您尝试删除 /id/registration 之一,并查看其他两个本身的行为方式是否相同?并尝试仅删除这两个无参数之一,看看会发生什么?我的直觉说这可能与无参数方法有关,但我没有这种预感的具体原因。
标签: java rest jax-rs websphere apache-wink