There are many tutorials on the internet where component object on JSF page is used.
Usually component.clientId or component.valid are used.
Example
<h:inputText .... styleClass="#{component.valid ? '' : 'ui-input-invalid'}"/>
If i create page with such component, i get an error:
javax.el.PropertyNotFoundException:
The class 'javax.faces.component.UIPanel' does not have the property 'valid'.
I googled that for inputText should be there UIInput class (which has isValid method), but i have there UIPanel (which dasn't).
Any idea why is there UI Panel?
(Java EE 6, JSF 2.1, Weblogic 12.1.2)
Whether or not a single component is valid is irrelevant in the long run; the entire request will be marked as invalid, even if it's as a result of the failure of a single component.
You should be retrieving the status of a request on the facesContext implicit EL object
<h:inputText .... styleClass="#{facesContext.validationFailed ? '' : 'ui-input-invalid'}"/>
Nothing I've seen in the 2.1 or 2.2 API supports the the presence of a valid attribute for the component implicit EL object. It's an implementation of javax.faces.component.UIComponent
Reference:
UIComponent Javadoc
Related
I'm trying to display image bytes which is saved in database as a StreamedContent in the <p:graphicImage> as follows:
<p:graphicImage value="#{item.imageF}" width="50" id="grpImage" height="80"/>
private StreamedContent content; // getter and setter
public StreamedContent getImageF() {
if (student.getImage() != null) {
InputStream is = new ByteArrayInputStream(student.getImage());
System.out.println("Byte :"+student.getImage());
content = new DefaultStreamedContent(is, "", student.getStuID());
System.out.println("ddd ------------------------------- " + content);
return content;
}
return content;
}
This returns a blank image. How is this caused and how can I solve it?
The stdout prints the following:
INFO: Byte :[B#a2fb48
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent#b0887b
INFO: Byte :[B#a2fb48
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent#1d06a92
INFO: Byte :[B#d52f0b
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent#39a60
INFO: Byte :[B#d52f0b
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent#8c3daa
INFO: Byte :[B#124728a
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent#1dbe05b
INFO: Byte :[B#124728a
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent#66a266
INFO: Byte :[B#a2fb48
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent#1293976
INFO: Byte :[B#a2fb48
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent#17b7399
INFO: Byte :[B#d52f0b
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent#1e245a5
INFO: Byte :[B#d52f0b
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent#4a7153
INFO: Byte :[B#124728a
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent#1561bfd
INFO: Byte :[B#124728a
INFO: ddd ------------------------------- org.primefaces.model.DefaultStreamedContent#47a8c2
The <p:graphicImage> requires a special getter method. It will namely be invoked twice per generated image, each in a completely different HTTP request.
The first HTTP request, which has requested the HTML result of a JSF page, will invoke the getter for the first time in order to generate the HTML <img> element with the right unique and auto-generated URL in the src attribute which contains information about which bean and getter exactly should be invoked whenever the webbrowser is about to request the image. Note that the getter does at this moment not need to return the image's contents. It would not be used in any way as that's not how HTML works (images are not "inlined" in HTML output, but they are instead requested separately).
Once the webbrowser retrieves the HTML result as HTTP response, it will parse the HTML source in order to present the result visually to the enduser. Once the webbrowser encounters an <img> element during parsing the HTML source, then it will send a brand new HTTP request on the URL as specified in its src attribute in order to download the content of that image and embed it in the visual presentation. This will invoke the getter method for the second time which in turn should return the actual image content.
In your particular case PrimeFaces was apparently either unable to identify and invoke the getter in order to retrieve the actual image content, or the getter didn't return the expected image content. The usage of #{item} variable name and the lot of calls in the log suggests that you were using it in an <ui:repeat> or a <h:dataTable>. Most likely the backing bean is request scoped and the datamodel isn't properly preserved during the request for the image and JSF won't be able to invoke the getter during the right iteration round. A view scoped bean would also not work as the JSF view state is nowhere available when the browser actually requests the image.
To solve this problem, your best bet is to rewrite the getter method as such so that it can be invoked on a per-request basis wherein you pass the unique image identifier as a <f:param> instead of relying on some backing bean properties which may go "out of sync" during subsequent HTTP requests. It would make completely sense to use a separate application scoped managed bean for this which doesn't have any state. Moreover, an InputStream can be read only once, not multiple times.
In other words: never declare StreamedContent nor any InputStream or even UploadedFile as a bean property; only create it brand-new in the getter of a stateless #ApplicationScoped bean when the webbrowser actually requests the image content.
E.g.
<p:dataTable value="#{bean.students}" var="student">
<p:column>
<p:graphicImage value="#{studentImages.image}">
<f:param name="studentId" value="#{student.id}" />
</p:graphicImage>
</p:column>
</p:dataTable>
Where the StudentImages backing bean can look like this:
#Named // Or #ManagedBean
#ApplicationScoped
public class StudentImages {
#EJB
private StudentService service;
public StreamedContent getImage() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
// So, we're rendering the HTML. Return a stub StreamedContent so that it will generate right URL.
return new DefaultStreamedContent();
}
else {
// So, browser is requesting the image. Return a real StreamedContent with the image bytes.
String studentId = context.getExternalContext().getRequestParameterMap().get("studentId");
Student student = studentService.find(Long.valueOf(studentId));
return new DefaultStreamedContent(new ByteArrayInputStream(student.getImage()));
}
}
}
Please note that this is a very special case wherein performing business logic in a getter method is completely legit, considering how the <p:graphicImage> works under the covers. Invoking business logic in getters is namely usually frowned upon, see also Why JSF calls getters multiple times. Don't use this special case as excuse for other standard (non-special) cases. Please also note that you can't make use of EL 2.2 feature of passing method arguments like so #{studentImages.image(student.id)} because this argument won't end up in the image URL. Thus you really need to pass them as <f:param>.
If you happen to use OmniFaces 2.0 or newer, then consider using its <o:graphicImage> instead which can be used more intuitively, with an application scoped getter method directly delegating to the service method and supporting EL 2.2 method arguments.
Thus so:
<p:dataTable value="#{bean.students}" var="student">
<p:column>
<o:graphicImage value="#{studentImages.getImage(student.id)}" />
</p:column>
</p:dataTable>
With
#Named // Or #ManagedBean
#ApplicationScoped
public class StudentImages {
#EJB
private StudentService service;
public byte[] getImage(Long studentId) {
return studentService.find(studentId).getImage();
}
}
See also the blog on the subject.
Try including a mime type. In your posted example, you have it as "". The blank image may be because it doesn't recognize the stream as a image file since you made that field an empty string. So add a mime type of image/png or image/jpg and see if that works:
String mimeType = "image/jpg";
StreamedContent file = new DefaultStreamedContent(bytes, mimeType, filename);
There's a couple possibilities here (and please post the entire class if this isn't it).
1) You're not initializing the image properly
2) Your stream is empty so you're getting nothing
I'm assuming student.getImage() has a signature of byte[] so first make sure that that data is actually intact and represents an image. Secondly--you're not specifying a content-type which should be "image/jpg" or whatever you're using.
Here's some boilerplate code to check it with, I'm using Primefaces 2 for this.
/** 'test' package with 'test/test.png' on the path */
#RequestScoped
#ManagedBean(name="imageBean")
public class ImageBean
{
private DefaultStreamedContent content;
public StreamedContent getContent()
{
if(content == null)
{
/* use your database call here */
BufferedInputStream in = new BufferedInputStream(ImageBean.class.getClassLoader().getResourceAsStream("test/test.png"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
int val = -1;
/* this is a simple test method to double check values from the stream */
try
{
while((val = in.read()) != -1)
out.write(val);
}
catch(IOException e)
{
e.printStackTrace();
}
byte[] bytes = out.toByteArray();
System.out.println("Bytes -> " + bytes.length);
content = new DefaultStreamedContent(new ByteArrayInputStream(bytes), "image/png", "test.png");
}
return content;
}
}
and some markup...
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui"
>
<h:head>
</h:head>
<h:body>
<p:graphicImage value="#{imageBean.content}" />
</h:body>
</html>
If that code works then you're set up properly. Despite the fact it is garbage code for the streams (don't use it in production) it should give you a point to troubleshoot from. My guess is that you might have something happening in your JPA or other Database framework where you're byte[] is empty or it is formatted wrong. Alternatively you could just have a content-type problem.
Lastly, I would clone the data from the bean so that student.getImage() would only be copied into a new array and then used. This way if you have something unknown going on (something else moving the object or changing the byte[] you're not messing with your streams.
Do something like:
byte[] data = new byte[student.getImage().length]
for(int i = 0; i < data.length; i++)
data[i] = student.getImage()[i];
so that your bean has a copy (or Arrays.copy()--whatever floats your boat). I can't stress enough how something simple like this/content type is usually what's wrong. Good luck with it.
The answer from BalusC is (as usual) the correct one.
But keep one thing (as already stated by him) in mind. The final request is done from the browser to get the URL from the constructed <img> tag. This is not done in a 'jsf context'.
So if you try to e.g. access the phaseId (logging or whatever reason)
context.getCurrentPhaseId().getName()
This will result in a NullPointerException and the somehow misleading error message you will get is:
org.primefaces.application.resource.StreamedContentHandler () - Error in streaming dynamic resource. Error reading 'image' on type a.b.SomeBean
It took me quite some time to figure out what was the problem.
Using JSF 2 on JBoss AS 7
Getting the following error:
07:36:39,579 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (http-/172.20.91.126:12580-16)
Error Rendering View[/views/afgarendesok.xhtml]:
com.sun.faces.mgbean.ManagedBeanCreationException:
Unable to set property searchManager for managed bean afgArendeBacking
at com.sun.faces.mgbean.ManagedBeanBuilder$BakedBeanProperty.set(ManagedBeanBuilder.java:615)
The searchManager property is defined in the AfgArendeBacking class as:
#ManagedProperty(value="#{afgArendeSokManager}")
private AfgArendeSokManager searchManager;
#Override
public AfgArendeSokManager getSearchManager() {
return searchManager;
}
public void setSearchManager(AfgArendeSokManager searchManager) {
this.searchManager = searchManager;
}
The AfgArendeSokManager is a #ManagedBean that is #SessionScoped.
Two things I don't get. One is why the error shuts down all usage of JSF not just for the session producing the error. The error seems to appear after non-usage both below the default session timeout and beyond. The other odd this is that a null pointer exception at line 606 in the BakedBeanProperty has to be the one the writeMethod variable. That variable is created via the PropertyDescriptor.getWriteMethod() call. This should have bombed earlier when creating baked bean (i.e. bakeBeanProperty method).
Any ideas how to debug? The property "searchManager" is resolved correctly since we can use the JSF views normally (both the getter/setter exist).
The search manager is our session scratch pad for propagating stuff between view and request scoped backing beans.
The article explains the issue of using reflection to access methods with covariant return types (see here: https://dzone.com/articles/covariant-return-type-abyssal). The article relates to Java 6 but the background information is very useful.
The issue you're facing and that hit us just this week (using Java 1.7.0_40) is not one of EL but of the java.beans.Introspector.
We are upgrading from jsf 1.2 to jsf 2.
We are using apache myfaces 2.1 and rich faces 4.3.
Below is the xhtml code prior to migration :
<h:inputText id="#{userSearch}" value="#{bean.input}"/>
<rich:suggestionbox for="#{userSearch}" var="rslt" suggestionAction="#{bean.getSearchList}">
</rich:suggestionbox>
As per migration doc , replaced <rich:suggestionbox> with <rich:autocomplete>.
Following is the xhtml code :
<rich:autocomplete mode="ajax" autocompleteMethod="#{bean.getSearchList}" />
Below is the getSearchList method
public List<CustomObject> getSearchList(String searchNow) {
}
The <rich:autocomplete> component exists inside a custom component which is invoked like this :
<example:SearchUsr bean="#{someOtherObject.bean}"/>
The issue i am facing is , when an input is entered inside <rich:autocomplete> , ajax call happens but i am am getting below exception :
Target Unreachable, identifier 'bean' resolved to null.
I printed the value of bean (of bean.getSearchList ) inside xhtml and it is not null.
Am i missing anything while using <rich:autocomplete> ? Please help.
EDIT 1 :
When the autocompleteMethod is invoked like this : #{masterBean.object2.object3.getSearchList}, this issue is not observed where masterBean is the one defined in faces-config.xml with session scope. Also autocompleteMethod must accept String argument and not object.
So is it that we cannot invoke autocompleteMethod on an intermidiate object ? It has to be a bean defined in JSF ? It is strange , but I am observing the same behaviour.
EDIT 2 :
While trying to search for an answer , got this link which states the same issue : autocomplete method does not resolve bean if ui:included and only one parameter provided
It gives two options : define autocomplete method with 3 parameters , use a composite component, rather than a ui:inlcude.
As evident from EDIT 2 , the autocomplete method signature is changed as :
public List<CustomObject> getSearchList(FacesContext context, UIComponent uiComp,String searchNow) , and the issue is resolved.
I am getting an javax.el.ELException: java.lang.Short cannot be cast to java.lang.Long for the following code:
<ui:param name="aumSegmentType" value="#{segmentSetup.userSegmentTypes[2]}" />
I am using Mojarra 2.1, facelets.
That's not possible. Numbers are in EL by specification treated as Long.
If changing the map key type isn't an option, then you need to create a method which takes a long and casts it to short.
public SomeObject getUserSegmentType(long key) {
return userSegmentTypes.get((short) key);
}
and use it as follows
<ui:param ... value="#{segmentSetup.getUserSegmentType(2)}" />
I of course assume that your environment already supports EL 2.2. It should, given the fact that you're using JSF 2.1.
Note that this problem is unrelated to JSF/Facelets.
When I access a JPA managed date value from JSF, it comes back with an javax.faces.component.UdateModelException saying
'Cannot convert 01.01.10 00:00 of type class java.util.Date to class org.apache.openjpa.util.java$util$Date$proxy
Using a JPA-managed date value (which means it is proxied) works fine when it is used directly from the EL likes this:
'<h:outputLabel value="MyDateValue" for="input"/>
'<h:inputText id="inputDate" value="#{bean.myDate}"/>
However, it causes trouble when trying to use it with composite components
and gives back the following converter exception and thus can't update the model...
The (simplified) JSF composite component inputDate.xhtml
<head>
<title>A date input field</title>
</head>
<composite:interface>
<composite:attribute name="dateValue"/>
</composite:interface>
<composite:implementation>
<h:outputLabel value="MyDateValue" for="input"/>
<h:inputText id="input" value="#{cc.attrs.dateValue}"/>
</composite:implementation>
Assumption:
It seems the proxy replacement in OpenJPA is handled differently when the value is being accessed from inside a composite. My guess is the EL-resolver handles calls to object values differently when it is passed to composites. Passing it to composites means it is first accessed within the composite, which is too late and the required replacement of the proxy is not accomplished (thus the converter exception)
So I tried to change the Expression Language for MyFaces, but it didn't work in Websphere, even though I changed the class loading to parent last and provided el-impl and el-api from glassfish in the lib folder and inserted the necessary context-param for MyFaces
How do you guys use JPA-managed dates (or other proxied entities) in composite components???
If you are using the sun EL implementation you might use the following ELResolver which works around this issue:
public class BugfixELResolver extends ELResolver {
//...
#Override
public Class<?> getType(ELContext anElContext, Object aBase, Object aProperty) {
if (aBase.getClass().getCanonicalName().equals("com.sun.faces.el.CompositeComponentAttributesELResolver.ExpressionEvalMap")){
Object tempProperty=((Map)aBase).get(aProperty);
if (tempProperty!=null&&tempProperty.getClass().getCanonicalName().equals("org.apache.openjpa.util.java.util.Date.proxy")) {
anElContext.setPropertyResolved(true);
return java.util.Date.class;
}
}
return null;
}
}
Add it to the faces-config this way:
<el-resolver>
xxx.BugfixELResolver
</el-resolver>
This workaround can also be used in environments where you can not change the EL implementation (like websphere etc.).
Here is the workaround. The problem seems to be WebSpheres' ExpressionLanguage Implementation or rather the order resolvers are executed. Registering the JBoss EL implementation works and resolves the date proxies before calling the composite component. I also tried the Glassfish EL, but it didn't work either...
Registering a alternative EL is quite strange: The setting in web.xml for MyFaces is
<context-param>
<param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
<param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>
Additionally under WebContent/META-INF/services/ a file named javax.el.expressionFactory is needed with this single line org.jboss.el.ExpressionFactoryImpl. The class comes from jboss-el-2.0.2.CR1.jar
(sorry, couldn't find the link to a maven repo)
I will keep you updated once I find a better solution...