我在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),消息为“ null”,同时处理发送到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 {
//...
}
}
为了方便起见...上面的代码最终生成了这些uri:
GET /公共/事件
GET / public / v1 / incidents / {incidentId} / details
GET / public / v2 / incidents / {incidentId} / details
GET / public / incidents / {incidentId} /票
POST / public / incidents / {incidentId} /注册
POST /管理员/事件
PUT / admin / incidents / {incidentId}
删除/ admin / incidents / {incidentId}
PUT / admin / v1 / incidents / {incidentId} / details
PUT / admin / v2 / incidents / {incidentId} / details
POST / admin / incidents / {incidentId} /票
PUT / admin / incidents / {incidentId} /票
删除/ admin / incidents / {incidentId} / tickets / {detailsUrn}
GET /管理员/事件/注册/报告/下载
GET /管理员/事件/注册/报告/电子邮件
GET / admin / incidents / {incidentId} /注册
PUT / admin / incidents / {incidentId} /注册
那是很多代码;我本来想避免这种情况,但似乎有必要。另外,就其价值而言,直到我添加
AdminRegistrationResource
类之前,一切似乎一直在起作用。也许该类中的某个端点之一开始引起冲突?再次...感谢您的时间!
-----------更新#2 -----------
我以为我会在这里发布我最近的特定错误之一,希望它可以帮助解决问题。当我将此端点称为:
GET /公共/事件
我收到此错误消息:
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批注(如下面的注释所建议),并仅用“ /”替换了它,但在以下情况下仍然收到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 /公共/事件
可能与上述其他4个端点正常工作有关。而且,更重要的是,如果我将IncidentResource类更改为如下所示(将方法级别的@Path注释完全移到类级别),则所有5个端点都可以工作:
@Path("/public/incidents")
public class IncidentResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getIncidents() throws Exception {
//...
}
我感谢到目前为止与我在一起的每个人!
最佳答案
删除@ApplicationPath(“ / context”),或者不要在请求uri中使用/ context,或者只使用@ApplicationPath(“ /”),即使升级也不会中断。
上面所有不同的方法都应该起作用,但是对于您的版本,我建议使用@ApplicationPath(“ /”)并通过删除/ context更新您的请求uri,一切都应该按照您最初的意图工作。
Apache Wink尚不支持ApplicationPath。
https://issues.apache.org/jira/browse/WINK-398