o:graphicImage 抛出 java.lang.IllegalArgumentException: 参数类型不匹配

o:graphicImage throws java.lang.IllegalArgumentException: argument type mismatch

我无法显示我数据库中的图像,它们存储为 bytea,我正在这样映射它们:

@Entity
@Table(name = "photograph", schema = "public")
public class Photograph{
    private PhotographId id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "diagnostic_id", nullable = false, insertable = false, updatable = false)
    private Diagnostic diagnostic;

    @Column(name = "photograph_content_type")
    private String photographContentType;

    @EmbeddedId
    @AttributeOverrides({
        @AttributeOverride(name = "diagnosticId", column = @Column(name  = "diagnostic_id", nullable = false)),
        @AttributeOverride(name = "photo", column = @Column(name = "photo", nullable = false)),
        @AttributeOverride(name = "photographDescription", column = @Column(name = "photograph_description", nullable = false, length = 100)) })
    public PhotographId getId() {
       return this.id;
    }

//Getters and Setters...
}

这是 pk 的 可嵌入 class

@Embeddable
public class PhotographId{
    @Column(name = "diagnostic_id", nullable = false)
    private Long diagnosticId;
    @Column(name = "photo", nullable = false)
    private byte[] photo;
    @Column(name = "photograph_description", nullable = false, length = 100)
    private String photographDescription;

//Getters and Setters...
}

我可以毫无问题地将所有图像存储在数据库中。问题是当我想像这样在 p:dataTable 中显示它们时:

<p:dataTable id="dataTableLoadedPhotos"
                value="#{imageController.photographListUpdate}" var="image">
                <p:column headerText="Fotografías cargadas" width="110">
                    <o:graphicImage value="#{imageStreamer.getById(image.id)}"
                        alt="#{msgs['label.diagnostic.photograph.notFound']}" />
                </p:column>
            </p:dataTable>

我正在使用基于 The BalusC Code: ImageServlet and I tried to use o:graphicImagestreamer 但没有成功,mi 代码中缺少一些东西:

@ManagedBean
@ApplicationScoped
public class ImageStreamer {

@EJB
private PhotographService photographService;

public byte[] getById(PhotographId id) {
    try {
        return photographService.getContent(id);
    } catch (ServiceException e) {
        FacesMessage mensaje = new FacesMessage(
                FacesMessage.SEVERITY_ERROR,
                "Error al buscar la fotografía "
                        + id.getPhotographDescription(), e.getMessage());
        FacesContext.getCurrentInstance().addMessage(null, mensaje);
    }
    return null;
}
}

我还有一个带有@RequestScoped 的托管 bean:

@ManagedBean
@RequestScoped
public class ImageController {

@EJB
private PhotographService photographService;

@ManagedProperty(value = "#{diagnosticDataManager}")
private DiagnosticDataManager diagnosticDataManager;

private List<Photograph> photographListUpdate = new ArrayList<Photograph>();
private Photograph selectedPhoto;

/**
 * 
 */
public ImageController() {
    diagnosticDataManager = new DiagnosticDataManager();
}

@PostConstruct
public void init() {
    if (diagnosticDataManager.getDiagnostic().getDiagnosticId() != null)
        photographListUpdate = photographService
                .findPhotosByDiagnostic(diagnosticDataManager
                        .getDiagnostic());

    for (Photograph photograph : photographListUpdate) {
        byte[] imageContent = org.apache.commons.codec.binary.Base64
                .decodeBase64(photograph.getId().getPhoto());
        ExternalContext ec = FacesContext.getCurrentInstance()
                .getExternalContext();
        ec.getSessionMap()
                .put(photograph.getId().toString(),
                        imageContent);
    }
}
// Getters and setters....
}

因为我使用的是 maven,所以我的应用程序目录是这样的:

src
|----main
     |----webapp
          |----images

我的 server.log 出错了,我在页面中看不到图像,我的代码中缺少什么?

20:22:43,687 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/patientdiagnostics].[Faces Servlet]] (http-localhost/127.0.0.1:8080-1) JBWEB000236: Servlet.service() for servlet Faces Servlet threw exception: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_79]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_79]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_79]
at java.lang.reflect.Method.invoke(Method.java:606) [rt.jar:1.7.0_79]
at org.omnifaces.resourcehandler.GraphicResource.getInputStream(GraphicResource.java:241) [omnifaces-2.0.jar:2.0]
at com.sun.faces.application.resource.ResourceHandlerImpl.handleResourceRequest(ResourceHandlerImpl.java:260) [jsf-impl-2.1.28.redhat-3.jar:2.1.28.redhat-3]
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
at org.primefaces.application.resource.PrimeResourceHandler.handleResourceRequest(PrimeResourceHandler.java:74) [primefaces-5.1.jar:5.1]
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:591) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:295) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:105) [primefaces-5.1.jar:5.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:246) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:231) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:149) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.4.0.Final-redhat-19.jar:7.4.0.Final-redhat-19]
at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.4.0.Final-redhat-19.jar:7.4.0.Final-redhat-19]
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:169) [jboss-as-web-7.4.0.Final-redhat-19.jar:7.4.0.Final-redhat-19]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:145) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:97) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:102) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:653) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:926) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_79]

我也试过类似Display database blob images in <p:graphicImage> inside <ui:repeat>

的东西

如其 documentation and showcase

中所述

In case the property is a method expression taking arguments, each of those arguments will be converted to a string HTTP request parameter and back to actual objects using the converters registered by class as available via Application.createConverter(Class). So, most of standard types like Long are already implicitly supported. In case you need to supply a custom object as argument for some reason, you need to explicitly register a converter for it yourself via @FacesConverter(forClass).

<o:graphicImage> 将使用为参数类型 class 注册的 JSF 转换器将所有 EL 方法参数转换为字符串并返回。 JSF 已经内置了转换器,例如Long 类型,所以这就是他们开箱即用的原因。但是你有一个 PhotographId 类型作为 EL 方法参数,显然没有为此注册的 JSF 转换器。

您有 2 个选择:

  1. 不要提供整个实体作为参数。请改用其标识符,在您的情况下只是 Long.

    例如

    <o:graphicImage value="#{imageStreamer.getById(image.id.diagnosticId)}">
    

    并相应地改变 getById() 方法。

  2. PhotographId class 创建一个 JSF 转换器。

    @FacesConverter(forClass=PhotographId.class)
    public class PhotographIdConverter implements Converter {
    
        @Override
        public String getAsString(FacesContext context, UIComponent component, Object modelValue) {
            // Write code here which converts PhotographId to its unique String representation.
        }
    
        @Override
        public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
            // Write code here which coverts the PhotographId's unique String representation as created in above method back to the original PhotographId object.
        }
    
    }
    

也就是说,这个模型看起来很奇怪。照片的内容是复合键的一部分..??这在 SQL 和 Java 方面都非常非常低效。您不妨对其进行审查和修复(然后您需要相应地更改 <o:graphicImage> 用法)。

此外,您尝试添加到流媒体的 catch 块中的 faces 消息不会显示在任何地方,因为图像请求不代表 JSF 页面。你最好 log/mail 它。