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...
Related
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.
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
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.
I have custom classes that I currently instantiate within App.xaml as resources. I want to move these custom objects into a Merged ResourceDictionary, where they are used within styles, and keep them close to where they are used.
Here's an example of what I want, arbitrarily using fake converter objects, but they could be any custom object...
App.xaml (namespace declarations ommitted):
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Merged.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="SomeStyle" TargetType="SomeControl">
...
</Style>
...
</ResourceDictionary>
And then in Merged.xaml (namespace declarations omitted):
<ResourceDictionary>
<cvt:VisibilityToBoolConverter x:Key="BoolToVisibility" Inverted="True"/>
<cvt:VisibilityToBoolConverter x:Key="NotBoolToVisibility" Inverted="True" Not="True"/>
<Style x:Key="SomethingThatUsesVisibilityToBoolConvertersStyle" TargetType="SomeOtherControl">
....
</Style>
</ResourceDictionary>
The issue I'm seeing is this: when I create the BoolToVisibility and NotBoolToVisibility objects (as well instantiating other objects that are instances of custom classes I have created) just as part Application.Resources, they are created and all the references work as expected; however, when I move these into a Merged Resource Dictionary (as I have in the sample above), I get a malformed Application exception when the Silverlight application loads.
I belive this to be an issue with how objects are instantiated differently in Merged Resource Dictionaries (I belive it is more of a lazy-load approach), but I would expect it to work nonetheless.
I am very much able to add Style objects, DataTemplates, ControlTemplates, and the like. But when I want to create instances of custom classes that are named or keyed using Xaml, it works great inside of App.xaml's Application.Resources directly and Application.Resources/ResourceDictionary as well. As soon as they are moved into a merged dictionary, it throws the exception. Is this by design? Any other ideas that work? Thanks in advance...
I have FINALLY worked around this. I took a page out of how the App class gets instantiated and did the same with the Merged.xaml file. I created a class with "code-behind" for Merged.xaml, called Merged that inherits from ResourceDictionary. I then (borrowing from App.g.cs), I initialize the component by loading from the Merged.xaml file during construction.
Merged.xaml.cs:
public partial class Merged : ResourceDictionary
{
private bool _contentLoaded;
public Merged()
{
InitializeComponent();
}
public void InitializeComponent()
{
if (_contentLoaded)
{
return;
}
_contentLoaded = true;
System.Windows.Application.LoadComponent(this, new System.Uri("/MySilverlightApp;component/Merged.xaml", System.UriKind.Relative));
}
}
The Merged.xaml file looks exactly the same as in my original question, using ResourceDictionary as it's root element.
The App.xaml is SLIGHTLY different. Instead of referencing the Merged ResourceDictionary by using the ResourceDictionary element and the Source attribute, I simply referenced the Merged class:
<Application.Resources
xmlns:msa="clr-namespace:MySilverlightApplication">
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<msa:Merged />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="SomeStyle" TargetType="SomeControl">
...
</Style>
...
</ResourceDictionary>
</Application.Resources>
Viola! It works.
You can avoid the extra codebehind by setting the build action for your shared xaml to "Resource" and reference it as /AssemblyName;component/Shared.xaml. For a reason that mostly escapes me, referencing it in this way allows custom object instantiation to work properly.