【问题标题】:RESTful service empty responseRESTful 服务空响应
【发布时间】:2015-09-17 17:45:43
【问题描述】:

我尝试创建的 REST 服务有问题。我使用内置的 GlassFish 4.1 和 Jersay 2.1。

@Path("/driver")
@RequestScoped
public class DriverResource {
    private static Logger logger = LogManager.getLogger(DriverResource.class);

        @Inject
        private DriverManager driverManager;

        private SharedResponseFactory responseFactory = new SharedResponseFactory();

        @GET
        @Path("/login/{pesel}/{password}")
        @Produces("application/json")
        public Response logIn(@PathParam("pesel") String pesel, @PathParam("password") String password) {
            try {
                Driver driver = driverManager.logIn(pesel, password);

                logger.debug("Zalogowano kierowcę: " + driver.getFullName());
                return responseFactory.getSuccesResponse(driver);
            } catch (ErrorDAOException e) {
                logger.catching(e);
                return responseFactory.getFailureResponse(e);
            } catch (NoDataFoundDAOException e) {
                logger.catching(e);
                return responseFactory.getFailureResponse(e);
            } catch (Exception e) {
                logger.catching(e);
                return responseFactory.getFailureResponse(e);
            }
        }
    }

当我尝试返回我的实体时,我得到如下响应:

{}

在我的实体中有很多循环引用,我不是在实际实现上操作,而是在接口上操作。我需要让它成为我的 Android 应用程序中的 Retrofit 可以反序列化它的方式。

Glassfish 的日志是空的,没有与 rest 相关的错误。我不知道如何使它工作。

我尝试使用@JsonIdentityInfo 处理循环引用并使用@JsonTypeInfo 使接口可以反序列化。

我认为有一个小技巧可以让它发挥作用,但不幸的是我不知道......

【问题讨论】:

    标签: java android json rest glassfish


    【解决方案1】:

    我找到了一种相对简单的方法来测试循环引用。如果您使用 JAXB(包含在 glassfish 中),您可以尝试将您的实体编组为 XML。如果找到任何循环引用,则会引发 JAXBException。

    这是一种将对象编组为 XML 的方法:

    public static <T> String marshalToXml(T instance) throws javax.xml.bind.JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(instance.getClass());
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        StringWriter writer = new StringWriter();
        jaxbMarshaller.marshal(instance, writer);
        return writer.toString();
    }
    

    并且服务可以像这样测试对象:

    @Path("/driver")
    @RequestScoped
    public class DriverResource {
    
        private static Logger logger = LogManager.getLogger(DriverResource.class);
    
        @Inject
        private DriverManager driverManager;
    
        private SharedResponseFactory responseFactory = new SharedResponseFactory();
    
        @GET
        @Path("/login/{pesel}/{password}")
        @Produces("application/json")
        public Response logIn(@PathParam("pesel") String pesel, @PathParam("password") String password) {
            try {
                Driver driver = driverManager.logIn(pesel, password);
    
                marshalToXml(driver); //remember to import static method
    
                logger.debug("Zalogowano kierowcę: " + driver.getFullName());
                return responseFactory.getSuccesResponse(driver);
            } catch (ErrorDAOException e) {
                logger.catching(e);
                return responseFactory.getFailureResponse(e);
            } catch (NoDataFoundDAOException e) {
                logger.catching(e);
                return responseFactory.getFailureResponse(e);
            } catch (JAXBException e) {
                //view error message to see cyclic reference
                logger.catching(e);
                return responseFactory.getFailureResponse(e);
            } catch (Exception e) {
                logger.catching(e);
                return responseFactory.getFailureResponse(e);
            }
        }
    }
    

    【讨论】:

    • 但有时我想保留这个循环引用。有没有办法使用杰克逊和@JsonIdentityInfo
    • 很遗憾没有。序列化 JSON 的核心是一个字符串。如果存在循环引用,字符串将变得不可能深。 JSON 规范有一种维护这些引用的方法(使用 $ref 属性),但是您可能必须自己在客户端解析结构。查看 This link 关于 $ref 属性的信息并阅读 this post 了解更多关于 JSON 解析的信息。
    • 如果您愿意,您可以在 JSON 结构中拥有属性,作为其他 JSON 对象的 ID。然后,您可以创建用于通过 id 查找这些 JSON 对象的休息服务。
    • 我发现了这样的东西:link。我可以用这个吗?当我添加注释时,它根本没有工作。有没有办法配置它?
    • 您可以这样做来自动为您创建 JSON 引用 ID,但在客户端(Web 浏览器或 Android 应用程序)上,您必须使用这些 ID 重新创建结构。这意味着您必须单独发送循环实体。杰克逊可能有办法为你做到这一点,但我不太熟悉。
    猜你喜欢
    • 2019-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 2015-08-03
    相关资源
    最近更新 更多