接口的自定义 jax-rs 实体提供程序?

发布于 2024-12-16 01:53:21 字数 2490 浏览 1 评论 0原文

我如何告诉 RESTEasy(一个 jax-rs 实现),“嘿,当您被要求提供 IFoo 时,只需继续创建一个 Foo 对象即可?”

我当前(错误的)尝试

有一个 api 访问点,我想使用它来使用 ReportPieceDAO 对象。 ReportPieceDAO 具有 List 成员。 StandardScoreReport是一个接口,由StandardScoreReportImpl实现。

@Path("pieces")
@PUT
@Produces("application/json")
@Consumes("application/json")
public Iterable<Long> putReportPiece( List<ReportPieceDAO> reportPieces) {
    return getDataCoordinator().updateReportPieces(getAuthenticatedUser(), reportPieces);
}

在我添加 List 成员之前,此入口点运行良好。由于 StandardScoreReport 是一个抽象接口,RESTEasy 无法自动构造一个抽象接口 - 它抱怨 StandardScoreReport 没有默认构造函数。

因此,我想制作某种适配器或提供程序,在需要 StandardScoreReport 的情况下构建 StandardScoreReportImpl

@Provider
@Consumes("application/json")
public class StandardScoreReportProvider implements MessageBodyReader<StandardScoreReport>{

    @Override
    public boolean isReadable(Class<?> arg0, Type arg1, Annotation[] arg2,
            MediaType arg3) {
        return true;
    }

    @Override
    public StandardScoreReport readFrom(Class<StandardScoreReport> arg0,
            Type arg1, Annotation[] arg2, MediaType arg3,
            MultivaluedMap<String, String> arg4, InputStream arg5)
            throws IOException, WebApplicationException {

            //I'm hoping I can just call some "default" code that 
            //would run if StandardScoreReportImpl were naturally 
            //encountered, and not have to write my own unmarshalling code.

        return new StandardScoreReportImpl();
    }

}

但这些代码都不会被执行。这是我的应用程序描述:

public class RESTEasyApplicationDescription extends Application
{
    HashSet<Class<?>> classes = new HashSet<Class<?>>();

    public RESTEasyApplicationDescription()
    {
        classes.add(APIRoot.class);
        classes.add(ReportsRoot.class);
        classes.add(StandardScoreReportProvider.class);
        classes.add(StandardScoreReport.class);
        classes.add(ReportPiece.class);
    }

    @Override
    public Set<Class<?>> getClasses() {
        return classes;
    }

    @Override
    public Set<Object> getSingletons() {
        return null;
    }
}

How can I tell RESTEasy (a jax-rs implementation), "Hey, when you get asked for IFoo, just go ahead and make a Foo object?"

My current (erroneous) attempt

I have an api access point that I would like to consume ReportPieceDAO objects. ReportPieceDAO has as a List<StandardScoreReport> member. StandardScoreReport is an interface, implemented by StandardScoreReportImpl.

@Path("pieces")
@PUT
@Produces("application/json")
@Consumes("application/json")
public Iterable<Long> putReportPiece( List<ReportPieceDAO> reportPieces) {
    return getDataCoordinator().updateReportPieces(getAuthenticatedUser(), reportPieces);
}

This entry point worked well before I added the List<StandardScoreReport> member. Because StandardScoreReport is an abstract interface, RESTEasy can't automatically construct one - it complains that StandardScoreReport has no default constructor.

So, I wanted to make some sort of adapter or provider that constructed a StandardScoreReportImpl in cases where a StandardScoreReport was required:

@Provider
@Consumes("application/json")
public class StandardScoreReportProvider implements MessageBodyReader<StandardScoreReport>{

    @Override
    public boolean isReadable(Class<?> arg0, Type arg1, Annotation[] arg2,
            MediaType arg3) {
        return true;
    }

    @Override
    public StandardScoreReport readFrom(Class<StandardScoreReport> arg0,
            Type arg1, Annotation[] arg2, MediaType arg3,
            MultivaluedMap<String, String> arg4, InputStream arg5)
            throws IOException, WebApplicationException {

            //I'm hoping I can just call some "default" code that 
            //would run if StandardScoreReportImpl were naturally 
            //encountered, and not have to write my own unmarshalling code.

        return new StandardScoreReportImpl();
    }

}

But none of this code is ever executed. Here's my application description:

public class RESTEasyApplicationDescription extends Application
{
    HashSet<Class<?>> classes = new HashSet<Class<?>>();

    public RESTEasyApplicationDescription()
    {
        classes.add(APIRoot.class);
        classes.add(ReportsRoot.class);
        classes.add(StandardScoreReportProvider.class);
        classes.add(StandardScoreReport.class);
        classes.add(ReportPiece.class);
    }

    @Override
    public Set<Class<?>> getClasses() {
        return classes;
    }

    @Override
    public Set<Object> getSingletons() {
        return null;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一杆小烟枪 2024-12-23 01:53:21

当您将应用程序部署到服务器时,会注册提供程序。服务器自动知道如何处理接收/传递某个对象。
您必须创建一个具有 @Provider 的类,然后如果您

从 POST 创建一个 java 对象,您可以使用:@Consumes
从您可以使用的 Web 服务调用发送 java 对象到 Response:@Produces

并指定类型。

示例:
我有一项服务,当我打电话时给我一个 PDF,它不消耗任何东西,它只给我一个 pdf 文件:

MyService.java

@GET
@Path("/report.{format}")
@Produces({ MediaType.TEXT_HTML, "application/pdf" })
public Response recuperarReporte(){
    private ByteArrayOutputStream responseEntity = ....;
    Response
            .ok()
            .entity(responseEntity)
            .type("application/pdf").build();
}

MyPDFProvider.java

@Produces("application/pdf")
@Provider
public class MyPDFProvider implements MessageBodyWriter<ByteArrayOutputStream>
{

    @Override
    public long getSize(ByteArrayOutputStream stream, Class<?> type,
            Type genericType, Annotation[] annotations, MediaType mediaType)
    {
        return stream.size();
    }

    @Override
    public boolean isWriteable(Class<?> type, Type genericType,
            Annotation[] annotations, MediaType mediaType)
    {
        return ByteArrayOutputStream.class.isAssignableFrom(type);
    }

    @Override
    public void writeTo(ByteArrayOutputStream t, Class<?> type,
            Type genericType, Annotation[] annotations, MediaType mediaType,
            MultivaluedMap<String, Object> httpHeaders,
            OutputStream entityStream) throws IOException,
            WebApplicationException
    {
        entityStream.write(t.toByteArray());
    }
}

Providers are registered when you deploying the application to the server. The server automatically know how handle receive / deliver a certain object.
You must create a class that has the @Provider and then if you

Create a java object from POST you may use: @Consumes
Send a java object to Response from a webservice call you may use: @Produces

and specifying the type.

Example:
I have a service that gives me a PDF when I call, it's no consumes nothing, it's only give to me a pdf file:

MyService.java

@GET
@Path("/report.{format}")
@Produces({ MediaType.TEXT_HTML, "application/pdf" })
public Response recuperarReporte(){
    private ByteArrayOutputStream responseEntity = ....;
    Response
            .ok()
            .entity(responseEntity)
            .type("application/pdf").build();
}

MyPDFProvider.java

@Produces("application/pdf")
@Provider
public class MyPDFProvider implements MessageBodyWriter<ByteArrayOutputStream>
{

    @Override
    public long getSize(ByteArrayOutputStream stream, Class<?> type,
            Type genericType, Annotation[] annotations, MediaType mediaType)
    {
        return stream.size();
    }

    @Override
    public boolean isWriteable(Class<?> type, Type genericType,
            Annotation[] annotations, MediaType mediaType)
    {
        return ByteArrayOutputStream.class.isAssignableFrom(type);
    }

    @Override
    public void writeTo(ByteArrayOutputStream t, Class<?> type,
            Type genericType, Annotation[] annotations, MediaType mediaType,
            MultivaluedMap<String, Object> httpHeaders,
            OutputStream entityStream) throws IOException,
            WebApplicationException
    {
        entityStream.write(t.toByteArray());
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文