从一个月前开始,我正在努力学习宁静的网络服务.现在我练习了语法并理解了概念,我决定创建一个包含EJB,JPA和REST的非常简单的企业应用程序.我正在努力尝试了解组织这种系统的最佳方法.如果有经验的人可以给我一些关于什么是最佳实践的提示,我会非常感激,以及如何解决我当前的问题.
我来告诉你这个形象吧.抱歉,我无法获得更好的分辨率(使用Ctrl +鼠标向上滚动缩放):

正如您所看到的,这是一个非常简单的企业应用程序,它有2个模块.
此应用程序不使用CDI(我希望在没有CDI帮助的情况下实现我的目标)
当某个客户端(任何可互操作的客户端)发送带有某些参数的@GET时,REST服务应将这些参数传递给EJB模块,该模块将在数据库中搜索并发回适当的数据.最后,服务将在JAXB的帮助下自动编组,并将.XML发送回客户端.
我的问题如下:
我有一个类,我想通过Jersey RESTful API公开.它看起来类似于:
@XmlRootElement
public class Data {
public String firstName;
public String lastName;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是这些字段可能为null,在这种情况下,字段从JSON输出中省略.我希望所有领域都存在,无论它们的价值如何.例如,如果lastName为null,则JSON输出将为:
{
"firstName" : "Oleksi"
}
Run Code Online (Sandbox Code Playgroud)
而不是我想要的:
{
"firstName" : "Oleksi",
"lastName" : null
}
Run Code Online (Sandbox Code Playgroud)
我有一个JAXBContextResolver(ContextResolver的实现),如下所示:
@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
// internal state
private final JAXBContext context;
private final Set<Class> types;
private final Class[] cTypes = { Data.class };
public JAXBContextResolver()
throws Exception {
types = new HashSet(Arrays.asList(cTypes));
context = new JSONJAXBContext(JSONConfiguration.natural().humanReadableFormatting(true).build(), cTypes);
}
@Override
public JAXBContext getContext(Class<?> objectType) {
return (types.contains(objectType)) …Run Code Online (Sandbox Code Playgroud) 当我尝试运行JAX-RS时,我收到错误消息,我怎么能让它工作?PlayerManagementLocal是@Local的ejb PlayerManagement工作正常.
错误信息
com.sun.jersey.api.container.ContainerException: An instance of EJB class rest.JSONService could not be looked up using simple form name or the fully-qualified form name.Ensure that the EJB/JAX-RS component implements at most one interface
Run Code Online (Sandbox Code Playgroud)
jaxrs.java
package rest;
import javax.ejb.EJB;
import javax.ejb.Stateful;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import prayForHunt.model.Person;
import prayForHunt.sb.PlayerManagement;
import prayForHunt.sb.PlayerManagementLocal;
@Stateless
@Path("/json")
public class JSONService {
@EJB
PlayerManagementLocal playerManagement;
@GET
@Path("/get/login/{login}/{heslo}")
@Produces(MediaType.APPLICATION_JSON)
public String getTrackInJSON(@PathParam("login") String login, @PathParam("heslo") String heslo) {
return "ahojky";
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用@Produces,@Consumes注释和JAXB 创建和运行JAX-RS的简单示例.
@Stateless
@LocalBean
@Path("/hotel")
public class RestMain {
@GET
@Produces(MediaType.APPLICATION_XML)
@Path("{hotelId}")
public HotelRESTInfo read(@PathParam("hotelId") long hotelId) {
HotelDataSourceFake hotelDataSourceFake = new HotelDataSourceFake();
HotelRESTInfo hotelInfo = hotelDataSourceFake.getFakePlaceById(hotelId);
return hotelInfo;
}
}
Run Code Online (Sandbox Code Playgroud)
web.xml中:
<servlet>
<servlet-name>REST App</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Run Code Online (Sandbox Code Playgroud)
第二个应用程序是客户端.现在我有以下客户端代码:
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
...
Client client = Client.create();
String uri ="http://localhost:8080/RESTJEE/rest/hotel/" + hotelId;
WebResource resource = client.resource(uri);
ClientResponse response = resource.accept("application/xml").get(ClientResponse.class);
HotelRESTInfo hotelRestInfo = response.getEntity(HotelRESTInfo.class);
Run Code Online (Sandbox Code Playgroud)
但我不想使用jersey的Client,ClientResponse和WebResource.我想这样做@Consumes …
我目前使用CXF公开了RESTFul Web服务.方法看起来像这样.
@GET
@Path("/getProfile/{memberno}/{userid}/{channelid}")
@Consumes("application/xml")
public MaintainCustomerProductResponse getUserDetails(
@PathParam("memberno") String membernumber,
@PathParam("userid") String userid,
@PathParam("channelid") String channelid){
//DO Some Logic here.
}
Run Code Online (Sandbox Code Playgroud)
这可以通过以下URL访问,并在提交有效数据时获得响应.
http://server.com:8080/UserService/getProfile/{memberno}/{userid}/{channelid}
Run Code Online (Sandbox Code Playgroud)
问题:如何传递null值userid?
如果我简单地忽略了{userId}请求是没有打在服务器端的Web服务.
例
http://server.com:8080/UserService/getProfile/1001//1
Run Code Online (Sandbox Code Playgroud)
注意:我正在使用SOAPUi测试并且没有给出userId值我看到以下响应SOAPUI并且请求没有命中服务器.
SOAPUI响应
<data contentType="null" contentLength="0"><![CDATA[]]></data>
Run Code Online (Sandbox Code Playgroud) 我正在寻找使用我的JAX-RS REST服务上的注释生成文档和客户端代码(使用各种语言,如Java,Scala,Ruby,JavaScript等)的工具.理想情况下,我想运行一个后期构建工具,给定我的REST服务类所在的包,将使用源代码上的(自定义)注释和一些最小配置生成文档和代码.Swagger的功能,但无需部署其servlet和所有这些东西.我试着弯曲swagger-codegen这样做没有运气.文档很小且分散,示例很少.我无法想象这不是一个解决的问题.想法?
我试图通过使其中一个方法需要HTTP基本身份验证来确保我的Web服务安全.为了做到这一点,我实现了一个自定义的Interceptor调用LoginInterceptor,它检查请求的URL,如果它对应于一个被调用的方法open,它会检查消息头是否有用户名和密码.
如果标头中没有验证字段,则响应代码设置为HTTP_UNAUTHORIZED,如果用户名或密码不正确,则将响应代码设置为HTTP_FORBIDDEN.这是代码:
public LoginInterceptor() {
super(Phase.RECEIVE);
addAfter(RequestInterceptor.class.getName()); //another custom interceptor, for some simple redirections.
}
public void handleMessage(Message message) throws Fault {
String requestURI = message.get(Message.REQUEST_URI).toString();
String methodKeyword = requestURI.substring("localhost".length()+1).split("/")[0];
if(methodKeyword.equals("open")) {
AuthorizationPolicy policy = message.get(AuthorizationPolicy.class);
if(policy == null) {
sendErrorResponse(message, HttpURLConnection.HTTP_UNAUTHORIZED);
return;
}
//userPasswords is a hashmap of usernames and passwords.
String realPassword = userPasswords.get(policy.getUserName());
if (realPassword == null || !realPassword.equals(policy.getPassword())) {
sendErrorResponse(message, HttpURLConnection.HTTP_FORBIDDEN);
}
}
}
//This is where the …Run Code Online (Sandbox Code Playgroud) 我正在尝试在我的客户端使用PATCH方法使用JAX-RS的CXF实现.起初我将PATCH注释定义为
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("PATCH")
public @interface PATCH {
}
Run Code Online (Sandbox Code Playgroud)
引用这里写的内容: 如何为JAX-RS提供@PATCH注释?
然后我发现@PATCH被添加到CXF 3.1.2中,所以我在我的maven的pom.xml中更改了版本,确实有public @interface PATCH内部版本,package org.apache.cxf.jaxrs.ext;代码实际上看起来与我上面发布的完全相同.
但是,当我尝试在我的服务定义上使用此注释时
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface AbcService {
@PATCH
@Path("/abc/efg")
public SomeDTO patchSomething(RequestObject request);
}
Run Code Online (Sandbox Code Playgroud)
我最终得到了java.net.ProtocolException: Invalid HTTP method: PATCH上面发布的queston链接中的说法.他们用Jersey讨论了一些解决方案,但是我可以在CXF中做什么,以便我可以使用:
AbcService abcService = JAXRSClientFactory.create(myURI, AbcService.class, myProviders, true);
abcService.patchSomething(new RequestObject('something'));
Run Code Online (Sandbox Code Playgroud)
所以我有几个问题:
设计一个可能在路径分辨率上有歧义的REST API被认为是不好的做法吗?例如:
GET /animals/{id} // Returns the animal with the given ID
GET /animals/dogs // Returns all animals of type dog
Run Code Online (Sandbox Code Playgroud)
好吧,这是设计的,因为你实际上只是这样做GET /dogs,但希望它说明了我的意思.从路径分辨率的角度来看,似乎你不知道你是在寻找动物id="dogs"还是只是所有动物dogs
具体来说,我对泽西岛是否会解决这个问题感兴趣.如果你知道它id是一个整数怎么办?
我正在使用JPA EclipseLink在UseCase和PainPoint之间建立一对多关系的模型。我能够很好地插入值。此后,我使用JAX-RS通过GET方法检索数据。GET方法失败,并显示错误- 生成不完整的JSON。
控制台日志:
用例:
@NamedQueries({@NamedQuery(name = "getAllUseCases", query = "SELECT c FROM UseCase c")})
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@NotNull
@Column(name = "UseCaseID")
private int UseCaseID;
@Column(name = "Description")
private String Description;
@OneToMany(mappedBy="usecase", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private Collection<PainPoint> painPoints = new ArrayList<PainPoint>();
Run Code Online (Sandbox Code Playgroud)
痛点:
@NamedQueries({@NamedQuery(name = "getAllPainPoints", query = "SELECT c FROM PainPoint c")})
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@NotNull
@Column(name = "PainPointID")
private int …Run Code Online (Sandbox Code Playgroud) jax-rs ×10
java ×6
rest ×6
cxf ×3
java-ee ×3
jersey ×2
json ×2
web-services ×2
eclipselink ×1
ejb ×1
get ×1
glassfish ×1
http-patch ×1
jackson ×1
jaxb ×1
null ×1
one-to-many ×1
swagger ×1