如何创建指向OmniFaces graphicImage方法的缩略图链接 [英] How to create a thumbnail link to OmniFaces graphicImage method
问题描述
我想知道是否可以在<p:lightbox>
内以缩略图的形式显示<o:graphicImage>
.更准确地说,我想实现以下目标:
<p:dataTable id="articles" var="article"
value="#{articleMB.articles}" selectionMode="single"
rowKey="#{articles.id}"
selection="#{articleMB.selectedArticle}">
<p:column>
<p:lightBox styleClass="imagebox" id="lighbox">
<h:outputLink value="#{imageBean.getFirstImage(article, true)}">
<o:graphicImage value="#{imageBean.getFirstImage(article, true)}" dataURI="true" height="80" />
</h:outputLink>
</p:lightBox>
</p:column>
</p:dataTable>
显然没有用,因为没有正确的URL传递到灯箱.
imageBean.getFirstImage(Article article, boolean thumbnail)
返回图像的byte[]
,因为我要访问的图像存储在外部源中.
因此,正如BalusC所述,我已经完成了操作,这似乎是正确的方法.但是现在我遇到了以下异常:
Caused by: java.lang.IllegalArgumentException: java.lang.ClassCastException@2eae887c
at sun.reflect.GeneratedMethodAccessor307.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.omnifaces.resourcehandler.GraphicResource.getInputStream(GraphicResource.java:259)
at com.sun.faces.application.resource.ResourceHandlerImpl.handleResourceRequest(ResourceHandlerImpl.java:335)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at org.primefaces.application.resource.PrimeResourceHandler.handleResourceRequest(PrimeResourceHandler.java:87)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:655)
... 32 more
这是实际返回图像的方法.在所有其他情况下都可以正常工作:
public byte[] getFirstImage(final Article article, boolean thumbnail)
{
try
{
File dir = new File(getImageFolder(article.getImageFolder(), thumbnail));
File[] files = dir.listFiles(new FilenameFilter()
{
@Override
public boolean accept(File dir, String name)
{
return name.startsWith(String.valueOf(article.getArticleId()));
}
});
Arrays.sort(files);
return Files.readAllBytes(files[0].toPath());
}
catch (Exception e)
{
return new byte[1];
}
}
如评论中所述,我面临着另一个奇怪的行为.它在我的本地计算机上运行得很好,但是在服务器上它抛出以下异常:
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.omnifaces.resourcehandler.GraphicResource.getInputStream(GraphicResource.java:259)
at com.sun.faces.application.resource.ResourceHandlerImpl.handleResourceRequest(ResourceHandlerImpl.java:335)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at org.primefaces.application.resource.PrimeResourceHandler.handleResourceRequest(PrimeResourceHandler.java:87)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:655)
... 32 more
正是由于这个原因,OmniFaces 2.5引入了#{of:graphicImageURL()}
EL函数.仅当您的ImageBean
用@GraphicImageBean
注释时,此方法才有效.
import org.omnifaces.cdi.GraphicImageBean;
@GraphicImageBean
public class ImageBean {
// ...
}
<h:outputLink value="#{of:graphicImageURL('imageBean.getFirstImage(article, false)')}">
<o:graphicImage value="#{imageBean.getFirstImage(article, true)}" dataURI="true" height="80" />
</h:outputLink>
另请参见 @GraphicImageBean
展示柜.
更新:为清楚起见,您需要一个用于非标准类型(例如Article
)的转换器. >转换错误"设置值中详细说明了为什么需要这样的转换器以及如何创建它表示空转换器" .如果创建@FacesConverter(forClass=Article.class)
,则OmniFaces GraphicImage
将自动拾取它.
在您的特定情况下,将标识符立即传递给流式图像方法会更有效,这样可以节省额外的转换步骤.前提是您的Article
对象具有id
属性,方法如下:
<h:outputLink value="#{of:graphicImageURL('imageBean.getFirstImage(article.id, false)')}">
<o:graphicImage value="#{imageBean.getFirstImage(article.id, true)}" dataURI="true" height="80" />
</h:outputLink>
public byte[] getFirstImage(Long articleId, boolean thumbnail) {
// ...
}
也就是说,JSF已经内置了用于标准类型(例如Long
和boolean
)的转换器.
I was wondering if and how it is possible to display an <o:graphicImage>
as thumbnail inside a <p:lightbox>
. To be more precise, I wanted to achieve something like this:
<p:dataTable id="articles" var="article"
value="#{articleMB.articles}" selectionMode="single"
rowKey="#{articles.id}"
selection="#{articleMB.selectedArticle}">
<p:column>
<p:lightBox styleClass="imagebox" id="lighbox">
<h:outputLink value="#{imageBean.getFirstImage(article, true)}">
<o:graphicImage value="#{imageBean.getFirstImage(article, true)}" dataURI="true" height="80" />
</h:outputLink>
</p:lightBox>
</p:column>
</p:dataTable>
Which isn't working obviously, since there's no proper URL passed to the lightbox.
imageBean.getFirstImage(Article article, boolean thumbnail)
returns a byte[]
of the image, since the images I want to access are stored on an external source.
Edit: So I've done as BalusC mentioned and it seems to be the proper approach. But now I'm getting the following exception:
Caused by: java.lang.IllegalArgumentException: java.lang.ClassCastException@2eae887c
at sun.reflect.GeneratedMethodAccessor307.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.omnifaces.resourcehandler.GraphicResource.getInputStream(GraphicResource.java:259)
at com.sun.faces.application.resource.ResourceHandlerImpl.handleResourceRequest(ResourceHandlerImpl.java:335)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at org.primefaces.application.resource.PrimeResourceHandler.handleResourceRequest(PrimeResourceHandler.java:87)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:655)
... 32 more
This is the method that actually returns the image. It is working fine in every other context:
public byte[] getFirstImage(final Article article, boolean thumbnail)
{
try
{
File dir = new File(getImageFolder(article.getImageFolder(), thumbnail));
File[] files = dir.listFiles(new FilenameFilter()
{
@Override
public boolean accept(File dir, String name)
{
return name.startsWith(String.valueOf(article.getArticleId()));
}
});
Arrays.sort(files);
return Files.readAllBytes(files[0].toPath());
}
catch (Exception e)
{
return new byte[1];
}
}
Edit 2: As mentioned in the comments, I'm facing another weird behaviour. It runs perfectly fine on my local machine but on the server it throws following exception:
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.omnifaces.resourcehandler.GraphicResource.getInputStream(GraphicResource.java:259)
at com.sun.faces.application.resource.ResourceHandlerImpl.handleResourceRequest(ResourceHandlerImpl.java:335)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at org.primefaces.application.resource.PrimeResourceHandler.handleResourceRequest(PrimeResourceHandler.java:87)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:655)
... 32 more
For exactly this reason, OmniFaces 2.5 introduced the #{of:graphicImageURL()}
EL function. This works only if your ImageBean
is annotated with @GraphicImageBean
.
import org.omnifaces.cdi.GraphicImageBean;
@GraphicImageBean
public class ImageBean {
// ...
}
<h:outputLink value="#{of:graphicImageURL('imageBean.getFirstImage(article, false)')}">
<o:graphicImage value="#{imageBean.getFirstImage(article, true)}" dataURI="true" height="80" />
</h:outputLink>
See also the @GraphicImageBean
showcase.
Update: to be clear, you need a converter for non-standard types such as Article
. Why such a converter is needed and how to create it is detailed in Conversion Error setting value for 'null Converter'. If you create a @FacesConverter(forClass=Article.class)
, then the OmniFaces GraphicImage
will automatically pickup it.
In your particular case it's however more efficient to just pass the identifier to the image streamer method right away, this saves an additional conversion step. Provided that your Article
object has an id
property, here's how:
<h:outputLink value="#{of:graphicImageURL('imageBean.getFirstImage(article.id, false)')}">
<o:graphicImage value="#{imageBean.getFirstImage(article.id, true)}" dataURI="true" height="80" />
</h:outputLink>
public byte[] getFirstImage(Long articleId, boolean thumbnail) {
// ...
}
Namely, JSF already has builtin converters for standard types such as Long
and boolean
.
这篇关于如何创建指向OmniFaces graphicImage方法的缩略图链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!