通过REST Web服务获取数据会产生异常 [英] Getting data through REST webservice gives exception

查看:234
本文介绍了通过REST Web服务获取数据会产生异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个使用REST将数据传递给客户端的Web服务。我现在卡在2个问题上,一个在客户端,一个在服务器端。我一直在尝试很多东西,然后我就更加困难了。我希望你们中的任何人都可以帮助我。

I'm trying to create a webservice which uses REST to pass on data to a client. I'm now stuck on 2 problems, one on the client side, and one on the server side. I've been trying a lot of things and I got even more stuck then I was before. I hope any of you can help me.

我尝试通过浏览器和应用程序来接近网络服务。如果我直接URL到服务器,我收到以下错误消息:

I tried approaching the webservice through the browser and throught the application. If I URL directly to the server, I get the following error message:

SEVERE: A message body writer for Java class java.util.ArrayList, and Java type java.util.Collection<domain.Tweet>, and MIME media type text/plain was not found
SEVERE: The registered message body writers compatible with the MIME media type are:
text/plain ->
  com.sun.jersey.core.impl.provider.entity.StringProvider
  com.sun.jersey.core.impl.provider.entity.ReaderProvider
*/* ->
  com.sun.jersey.core.impl.provider.entity.FormProvider
  com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider
  com.sun.jersey.core.impl.provider.entity.StringProvider
  com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
  com.sun.jersey.core.impl.provider.entity.FileProvider
  com.sun.jersey.core.impl.provider.entity.InputStreamProvider
  com.sun.jersey.core.impl.provider.entity.DataSourceProvider
  com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
  com.sun.jersey.core.impl.provider.entity.ReaderProvider
  com.sun.jersey.core.impl.provider.entity.DocumentProvider
  com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider
  com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter
  com.sun.jersey.server.impl.template.ViewableMessageBodyWriter
  com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONArrayProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONObjectProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONWithPaddingProvider
  com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$General
  com.sun.jersey.json.impl.provider.entity.JacksonProviderProxy
  com.sun.jersey.moxy.MoxyMessageBodyWorker
  com.sun.jersey.moxy.MoxyListMessageBodyWorker

如果我运行客户端应用程序,则会收到以下错误消息:

If I run the client application, I get the following error message:

Exception in thread "AWT-EventQueue-0" com.sun.jersey.api.client.UniformInterfaceException: GET http://localhost:8080/KwetterSOAP/resources/rest/user/Hans/tweets returned a response status of 500 Internal Server Error
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:688)
    at com.sun.jersey.api.client.WebResource.access$300(WebResource.java:74)
    at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:508)
    at service.RestClient.getTweets(RestClient.java:52)
    at kwettermonitor.KwetterFollowing.btnZoekFollowersActionPerformed(KwetterFollowing.java:103)
    at kwettermonitor.KwetterFollowing.access$000(KwetterFollowing.java:20)
    at kwettermonitor.KwetterFollowing$1.actionPerformed(KwetterFollowing.java:54)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6505)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
    at java.awt.Component.processEvent(Component.java:6270)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4861)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2713)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
    at java.awt.EventQueue.access$000(EventQueue.java:101)
    at java.awt.EventQueue$3.run(EventQueue.java:666)
    at java.awt.EventQueue$3.run(EventQueue.java:664)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:680)
    at java.awt.EventQueue$4.run(EventQueue.java:678)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

网络服务的创建如下:

@Path("/rest")
@Stateless
public class RESTService {

    @Inject @Named(value = "kwetterService")
    private KwetterService service;

    @GET
    @Path("/user/{user}")
    @Produces(MediaType.TEXT_PLAIN)
    public User getUser(@PathParam("user") String userName)
    {
        return service.findByName(userName);
    }

    @GET
    @Path("/user/{user}/tweets")
    @Produces(MediaType.TEXT_PLAIN)
    public Collection<Tweet> getTweets(@PathParam("user") String userName)
    {
        System.out.println("Service: " + service);
        User user = service.findByName(userName);
        System.out.println(userName);
        System.out.println(user);
        return user.getTweets();
    }

客户如下:

public class RestClient {
    private WebResource webResource;
    private Client client;
    private static final String BASE_URI = "http://localhost:8080/KwetterSOAP/resources";

    public RestClient() {
        DefaultClientConfig config = new DefaultClientConfig();
        client = Client.create(config);
        webResource = client.resource(BASE_URI).path("rest");
    }

    public User getUser(String userName) throws UniformInterfaceException {
        final WebResource.Builder userResource = webResource
           .path(String.format("/user/%s", userName))
           .accept(MediaType.TEXT_PLAIN) ;
        return userResource.get(User.class);
    }

    public Collection<Tweet> getTweets(String userName) throws UniformInterfaceException {
        final WebResource.Builder tweetResource = webResource
           .path(String.format("/user/%s/tweets", userName))
           .accept(MediaType.TEXT_PLAIN);
        return tweetResource.get(new GenericType<Collection<Tweet>>(){});
    }

我也有点困惑,是放在哪里@XML ...注释。我已将该服务注释为根元素:

The point I get a little bit confused over as well, is where to put the @XML... annotations. I've annotated the service as a Root Element:

@Named(value = "kwetterService")
@Stateless
@XmlRootElement
public class KwetterService {

我没有注释使用过的方法:

I didn't annotate the used method:

public User findByName(String name)
    {
        return userDAO.getUser(name);
    }

UserDAO接近数据库中的数据。我在这里没有为REST / XML添加任何内容。
我也为用户提供了一个XMLRootElement:

UserDAO approaches data in the database. I've added nothing for REST/XML here. I made User a XMLRootElement as well:

@Entity
@XmlRootElement
@Table(name="Users")
public class User implements Serializable {

方法getTweets (),我添加了XMLElement注释:

At the method getTweets(), I added the XMLElement annotation:

@XmlElement
    public Collection<Tweet> getTweets() {
        List<Tweet> temp = new ArrayList<Tweet>(tweets);
        Collections.reverse(temp);
        return temp;
    }

我自己的猜测是我对方法和类的整个注释是错误的。您可以看到任何错误吗?

My own guess is that my whole annotation of methods and classes is wrong. Any errors you can see?

推荐答案

请记住,JAX-RS的核心是建立在HTTP之上,而HTTP不是不了解或关心Java对象。从资源方法返回对象时,必须将它们转换为可由请求客户端使用的数据。此转换由名为 MessageBodyWriters 的实体完成,并且所有JAX-RS实现都需要预先包装它们。不幸的是,没有要求实现能够将您的对象转换为TEXT_PLAIN。从您发布的堆栈跟踪中,您实际上可以看到没有能够处理该媒体类型的提供商:

Remember that at its core, JAX-RS is built on top of HTTP, and HTTP doesn't know or care about Java objects. When you return objects from a resource method they have to be translated into data that can be consumed by the requesting client. This translation is done by entities called MessageBodyWriters, and all JAX-RS implementation are required to come with a prepackaged set of them. Unfortunately, there is no requirement that the implementation be able to translate your objects into TEXT_PLAIN. From the stacktrace you posted, you can actually see there is no provider capable of handling that media type:

com.sun.jersey.core.impl.provider.entity.FormProvider
com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider
com.sun.jersey.core.impl.provider.entity.StringProvider
com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
com.sun.jersey.core.impl.provider.entity.FileProvider
com.sun.jersey.core.impl.provider.entity.InputStreamProvider
com.sun.jersey.core.impl.provider.entity.DataSourceProvider
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
com.sun.jersey.core.impl.provider.entity.ReaderProvider
com.sun.jersey.core.impl.provider.entity.DocumentProvider
com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider
com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter

所有JAX-RS实现的翻译之一但是, 必须 提供从Java对象到XML的提供。因此,您可以安全地将其用作数据格式。仅显示更改,您需要合并到现有代码中:

One of the translations that all JAX-RS implementations must provide though, is one from Java objects to XML. So you can safely use that as your data format. Showing changes only, you will need to merge into your existing code:

Java Bean

Java Bean:

@Entity
@XmlRootElement
@Table(name="Users")
public class User implements Serializable {

    @XmlWrapperElement("tweets")
    public Collection<Tweet> getTweets() {
        List<Tweet> temp = new ArrayList<Tweet>(tweets);
        Collections.reverse(temp);
        return temp;
    }
}

服务器

Server:

@Path("/rest")
@Stateless
public class RESTService {
    @GET
    @Path("/user/{user}")
    @Produces(MediaType.APPLICATION_XML)
    public User getUser(@PathParam("user") String userName);

    @GET
    @Path("/user/{user}/tweets")
    @Produces(MediaType.APPLICATION_XML)
    public Collection<Tweet> getTweets(@PathParam("user") String userName);
}

客户

Client:

public class RestClient {
    public User getUser(String userName) throws UniformInterfaceException {
        final WebResource.Builder userResource = webResource
           .path(String.format("/user/%s", userName))
           .accept(MediaType.APPLICATION_XML) ;
        return userResource.get(User.class);
    }

    public Collection<Tweet> getTweets(String userName)
        throws UniformInterfaceException {
        final WebResource.Builder tweetResource = webResource
           .path(String.format("/user/%s/tweets", userName))
           .accept(MediaType.APPLICATION_XML);
        return tweetResource.get(new GenericType<Collection<Tweet>>(){});
    }
}

这篇关于通过REST Web服务获取数据会产生异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆