I have an application, which uses PrimeFaces Mobile to display images.
Sometimes, but not always, the image is not displayed fully - only the top part.
The XHTML code of the page with that image looks like this:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:pm="http://primefaces.org/mobile">
<f:view renderKitId="PRIMEFACES_MOBILE"/>
<h:head>
</h:head>
<f:event listener="#{main.loadFirstImage}" type="preRenderView" />
<h:body id="body">
<pm:page id="page">
<pm:header title="myapp">
</pm:header>
<pm:content id="content">
<h:form>
<p:graphicImage id="image" rendered="false" value="#{main.currentImage()}"
cache="false">
</p:graphicImage>
[...]
</h:form>
</pm:content>
<pm:footer title="m.myapp.com"></pm:footer>
</pm:page>
</h:body>
</html>
And the main
bean has following code:
@ManagedBean(name = "main")
@SessionScoped
public class MainView {
private byte[] currentImageData;
private byte[] productId;
private byte[] imageId;
public void loadFirstImage()
{
// This method initializes currentImageData
fetchNextImage();
}
[...]
public StreamedContent currentImage()
{
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
return new DefaultStreamedContent();
}
else {
return new DefaultStreamedContent(new ByteArrayInputStream(currentImageData));
}
}
[...]
}
How can I fix this error?
Update 1 (03.11.2014 23:21 MSK):
I've tried following to fix the error:
1) Disabling cache for all elements of that Primefaces page.
2) Disabling response chunking by setting maxExtensionSize
and maxTrailerSize
(server.xml
) to -1
.
3) Adding a filter with following doFilter
:
@Override
public void doFilter(final ServletRequest aServletRequest,
final ServletResponse aServletResponse,
final FilterChain aFilterChain) throws IOException, ServletException {
System.out.println("aServletRequest instanceof HttpServletRequest: " +
(aServletRequest instanceof HttpServletRequest));
if (aServletRequest instanceof HttpServletRequest)
{
final HttpServletRequest request = (HttpServletRequest) aServletRequest;
final String requestURI = request.getRequestURI().toLowerCase();
if (!requestURI.endsWith("/javax.faces.resource/dynamiccontent.properties"))
{
aFilterChain.doFilter(aServletRequest, aServletResponse);
}
}
}
4) Changing the currentImage
method to
public StreamedContent currentImage()
{
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
// So, we're rendering the view. Return a stub StreamedContent so that it will generate right URL.
return new DefaultStreamedContent();
}
else {
String mimeType = null;
if (imageFileName.toLowerCase().endsWith(".png"))
{
mimeType = "image/png";
}
else if (imageFileName.toLowerCase().endsWith(".jpeg") || imageFileName.toLowerCase().endsWith(".jpg"))
{
mimeType = "image/jpeg";
}
// So, browser is requesting the image. Return a real StreamedContent with the image bytes.
return new DefaultStreamedContent(new ByteArrayInputStream(currentImageData), mimeType);
}
}
But it still doesn't work. I wrote a piece of code in another web application and using different framework (Vaadin), which displays images from the same source.
I get the same error (images are displayed only partially).
From this I conclude that the error must occur
- when images are retrieved from a particular and/or
- when images are saved in MongoDB.
Code for retrieving images from URL
If the error occurs during reading the image, it occurs in the following method:
protected Binary readImage(final String viewItemURL) {
InputStream inputStream = null;
Binary image = null;
try
{
inputStream = new URL(viewItemURL).openStream();;
byte bytes[] = new byte[inputStream.available()];
inputStream.read(bytes);
image = new Binary(bytes);
}
catch (final IOException exception)
{
LOGGER.error("", exception);
}
finally
{
IOUtils.closeQuietly(inputStream);
}
return image;
}
viewItemURL
is the URL of the image.
Code for saving image in MongoDB
If the problem is with saving images in the database, it occurs in the following method:
protected void saveProductImages(final byte[] aNewProductId, final List<String> aPictureUrls,
final IMongoPersistenceState aPersistenceState) {
final DB db = aPersistenceState.getDb();
final DBCollection productImagesColl = db.getCollection(
MyAppPersistenceAction.COLLECTION_USER_PRODUCT_IMAGES);
for (final String curPictureUrl : aPictureUrls)
{
final Binary imageData = readImage(curPictureUrl);
final Map<String,Object> map = new HashMap<String, Object>();
map.put(FIELD_COLLECTION_USER_PRODUCT_IMAGES_CREATOR_EMAIL, CREATOR_EMAIL);
map.put(FIELD_COLLECTION_USER_PRODUCT_IMAGES_PRODUCT_ID, aNewProductId);
map.put(FIELD_COLLECTION_USER_PRODUCT_IMAGES_DATA, imageData);
final String fileName = extractFileName(curPictureUrl);
map.put(FIELD_COLLECTION_USER_PRODUCT_IMAGES_FILE_NAME, fileName);
map.put(FIELD_COLLECTION_USER_PRODUCT_IMAGES_MIME_TYPE, getMimeType(fileName));
map.put(FIELD_COLLECTION_USER_PRODUCT_IMAGES_IS_DELETED, Boolean.FALSE);
productImagesColl.insert(WriteConcern.SAFE, createRecordObject(map));
}
}
See Question&Answers more detail:
os