I've been stuck on this issue for a while now. I found a earlier post where BalusC gave advice on creating your own converter called "EmptyToNullConverter" for JSF version 1.2
or specifying a context parameter in JSF 2.0
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
None of these options has worked for me. Has it worked for other people.
Doing some investigation of my own I ended up stepping through the UIInput source. I can see the value is null until it is passed to the ValueExpression. Unfortunately I do not have the source for that so I could not drill down further. I'm assuming it is here where it ends up instantiating a new String Type and rather passing that to the model property?
My environment is as follows
running Mojarra RI using the jsf-api-2.0.3 and jsf-impl-2.0.3 jars
also using richfaces 3.3.3, so I had to disable the viewhandler for jsf2. Still using facelets jar as a result
All this is running on Tomcat 6
Any help will be appreciated
I know we had this problem using Richfaces and Sun's default JSF implementation 1.2.
One way to work around the problem is using your own custom converters for whatever type you need that convert empty values (0, "") to nulls.
Other way is doing the conversion inside your backingbean:
MyBackingBean {
String myValue;
public void setMyValue(String v) {
if (v==null || v.trim().length==0) {
myValue==null;
} else {
myValue=v;
}
}
public String getMyValue() {
return myValue;
}
}
Related
I tried to set up a simple JSF 2.2 application using MyFaces 2.2.8.
Since MyFaces has some context parameters that I never used before, I tried to get familiar with those.
So I got to use org.apache.myfaces.JSF_JS_MODE for the first time and ran into problems with h:commandLink.
The commandLink is trying to call myfaces.oam.submitForm() which is not defined if I set the mode to minimal-modern.
If I set the mode to minimal or normal it works.
From reading some internet articles I assume this is a bug because submitForm is neither part of jsf-legacy.js nor jsf-i18n.js nor jsf-experimental.js and it apparently is needed by h:commandLink.
Also the source code comment of org.apache.myfaces.shared.renderkit.html.util.ResourceUtils.markScriptAsRendered(FacesContext, String, String) tells me
oamSubmit script is included inside jsf.js
here:
public static void markScriptAsRendered(FacesContext facesContext, String libraryName, String resourceName)
{
getRenderedScriptResources(facesContext).put(
libraryName != null ? libraryName+'/'+resourceName : resourceName, Boolean.TRUE);
if (JAVAX_FACES_LIBRARY_NAME.equals(libraryName) &&
JSF_JS_RESOURCE_NAME.equals(resourceName))
{
// If we are calling this method, it is expected myfaces core is being used as runtime and note
// oamSubmit script is included inside jsf.js, so mark this one too.
getRenderedScriptResources(facesContext).put(
MYFACES_LIBRARY_NAME+'/'+MYFACES_JS_RESOURCE_NAME, Boolean.TRUE);
}
}
What am I missing here? Thanks in advance!
I can confirm it is a bug. Solved in MYFACES-4034 for 2.2.10
I tried to add OmniFaces HTML5 support to a project without success.
ICEFaces throws an severity error:
ICEfaces rendering required by icefaces-compat.jar components. Enable via <icecore:config render="true" />.
Error Renter code hereendering View[/index.xhtml]
So I added icecore:config render="true" but it didn't work, throws same error.
Not sure if it's a configuration mistake.
What I've done is add to web.xml:
<context-param>
<param-name>org.omnifaces.HTML5_RENDER_KIT_PASSTHROUGH_ATTRIBUTES</param-name>
<param-value>
javax.faces.component.UIInput=x-webkit-speech,x-webkit-grammar;
javax.faces.component.UIComponent=contenteditable,draggable
</param-value>
</context-param>
And in faces-config:
<factory>
<render-kit-factory>org.omnifaces.renderkit.Html5RenderKitFactory</render-kit-factory>
</factory>
If "factory" is removed from faces-config, the project works but without HTML5 support. It seems that HTML5 render kit overrides the icefaces's kit.
One other thing that makes me think it's a config mistake is that NetBeans underlines "placeholder" attribute in an h:inputText.
Indeed, as I suspected, ICEfaces thinks it's being the only JSF library in the webapp and is performing an immediate instanceof check on the FacesContext#getResponseWriter() without inspecting the wrapped ones. Here's an extract from ICEfaces' DOMContext class:
85 ResponseWriter responseWriter = facesContext.getResponseWriter();
86 DOMResponseWriter domWriter;
87 if (responseWriter instanceof DOMResponseWriter) {
88 domWriter = (DOMResponseWriter) responseWriter;
89 } else {
90 // domWriter = createTemporaryDOMResponseWriter(responseWriter, facesContext);
91 log.severe("ICEfaces rendering required by icefaces-compat.jar " +
92 "components. Enable via <icecore:config render=\"true\" />.");
93 throw new UnsupportedOperationException("ICEfaces rendering required.");
94 }
(note: starting at line 222 there's a similar block)
In theory, you could workaround this by explicitly registering the ICEfaces renderkit factory after the OmniFaces one in faces-config.xml. However, I couldn't find a RenderKitFactory in the ICEfaces source code who's responsible for creating the DOMRenderKit. It appears that ICEfaces thinks it's a JSF implementation by itself and altogether overriding the default JSF implementation's HTML_BASIC renderkit as follows in its /META-INF/faces-config.xml:
<render-kit>
<render-kit-id>HTML_BASIC</render-kit-id>
<render-kit-class>org.icefaces.impl.renderkit.DOMRenderKit</render-kit-class>
</render-kit>
All in all, ICEfaces doesn't make it possible anymore to wrap the render kits via a factory. This is not so nice. Note that the extracted source contains an outcommented line referencing createTemporaryDOMResponseWriter() which does its job -almost- right. Perhaps they couldn't figure why it didn't always work and left it for what it was. Too bad.
The workaround would be to copy the DOMContext class into your webapp, in its original package (once deployed, classes in /WEB-INF/classes have precedence over the ones in /WEB-INF/lib, so the custom copy would be loaded instead of the ICEfaces one) and change the code starting at line 85 as follows and remove the entire if-else block thereafter:
85 ResponseWriter responseWriter = facesContext.getResponseWriter();
86 DOMResponseWriter domWriter = findDOMResponseWriter(responseWriter);
(do the same for the block starting at line 222)
And add the following method:
private static DOMResponseWriter findDOMResponseWriter(ResponseWriter responseWriter) {
while (!(responseWriter instanceof DOMResponseWriter) && responseWriter instanceof ResponseWriterWrapper) {
responseWriter = ((ResponseWriterWrapper) responseWriter).getWrapped();
}
if (responseWriter instanceof DOMResponseWriter) {
return (DOMResponseWriter) responseWriter;
}
else {
throw new UnsupportedOperationException("ICEfaces rendering required");
}
}
That should do it for you.
I've a Groovy project where I use RESTEasy with Weld and deploy to embedded Jetty. What I can't seem to get working is bean validation. RESTEasy documentation says that adding resteasy-validator-provider-11 along with hibernate validator dependencies (hibernate-validator, hibernate-validator-cdi, javax.el-api, javax.el) is enough. But the bean validation is simply ignored by RESTEasy. I curiously also get the following message in the logs:
plugins.validation.ValidatorContextResolver - Unable to find CDI supporting ValidatorFactory. Using default ValidatorFactory
Based on the suggestions on [this][1] post, I tried registering Hibernate InjectingConstraintValidatorFactory in META-INF/validation.xml but it depends on a BeanManager being injected and blows up at runtime.
The code can be found here https://github.com/abhijitsarkar/groovy/tree/master/movie-manager/movie-manager-web
A log gist is here: https://gist.github.com/anonymous/8947319
I've tried everything under the sun without any success. Pls help.
To do this without EE, I believe you'll need to fork the existing InjectingConstraintValidatorFactory but instead of using injection of the bean manager, use the CDI 1.1 class CDI to get a reference to the bean manager, e.g. CDI.current().getBeanManager(). http://docs.jboss.org/cdi/api/1.1/javax/enterprise/inject/spi/CDI.html
You do need to be on CDI 1.1 to do this (so Weld 2+, 2.1.1 is current I believe). Here's an example impl, based on: https://github.com/hibernate/hibernate-validator/blob/master/cdi/src/main/java/org/hibernate/validator/internal/cdi/InjectingConstraintValidatorFactory.java
public class InjectingConstraintValidatorFactory implements ConstraintValidatorFactory {
// TODO look for something with better performance (HF)
private final Map<Object, DestructibleBeanInstance<?>> constraintValidatorMap =
Collections.synchronizedMap( new IdentityHashMap<Object, DestructibleBeanInstance<?>>() );
private final BeanManager beanManager;
public InjectingConstraintValidatorFactory() {
this.beanManager = CDI.current().getBeanManager();
Contracts.assertNotNull( this.beanManager, "The BeanManager cannot be null" );
}
#Override
public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
DestructibleBeanInstance<T> destructibleBeanInstance = new DestructibleBeanInstance<T>( beanManager, key );
constraintValidatorMap.put( destructibleBeanInstance.getInstance(), destructibleBeanInstance );
return destructibleBeanInstance.getInstance();
}
#Override
public void releaseInstance(ConstraintValidator<?, ?> instance) {
DestructibleBeanInstance<?> destructibleBeanInstance = constraintValidatorMap.remove( instance );
destructibleBeanInstance.destroy();
}
}
I finally fixed this. Turns out, a validation.xml is not really required, resteasy-cdi module does a fine job of registering the BeanManager. What I was missing and not clearly documented anywhere, is that if an annotation is placed on a method, the validation engine just "decides" what should be validated. I placed a #NotNull on a method and it was validating the return type, not the parameters. One can use validationAppliesTo element in some cases but #NotNull doesn't have it. When I moved it from the method to the parameter, it started working.
Now I ran across what I believe is a Weld bug but I'll post that question separately.
I have a JSF Validator that I'm building that has properties in it that I would like to have loaded from a ResourceBundle. However, I'm not quite sure how to work this, as it isn't loading properly. Any ideas on how I can make this work?
I've tried using a #PostContruct to do it, but I'm getting the following error in Eclipse:
Access restriction: The type
PostConstruct is not accessible due to
restriction on required library
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/classes.jar
So, I'm not too sure what the best way to work this. A sample of what I'm talking about is below...
The validator...
#FacesValidator("usernameValidator")
public class UserNameValidator implements Validator {
#ManagedProperty(value="#{props_userNamePattern}")
private String userNamePattern;
#ManagedProperty(value="#{props_minUserNameLength}")
private int minUserNameLength;
#ManagedProperty(value="#{props_maxUserNameLength}")
private int maxUserNameLength;
public void validate(FacesContext context, UIComponent component, Object
value) throws ValidatorException {
//My validations here...
}
//Setters for the class properties
}
faces-config.xml
<resource-bundle>
<base-name>settings</base-name>
</resource-bundle>
settings.properties
props_userNamePattern = /^[a-z0-9_-]+$/
props_minUserNameLength = 3
props_maxUserNameLength = 30
The #ManagedProperty works on #ManagedBean classes only. The #PostConstruct will also not be the correct solution for your functional requirement. It is intented to be placed on a method which is to be executed when the class has been constructed and all dependency injections are been finished. The error which you're facing is caused by a specific combination of older Eclipse+JRE versions. If upgrading is not an option, you could disable the warning/error by Window > Preferences > Java > Compiler > Errors/Warnings > Deprecated and restricted API > Forbidden reference > Ignore.
As to your functional requirement, unfortunately no annotation which achieves that comes to mind. You could however get it programmatically.
String bundlename = "settings";
Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
ResourceBundle bundle = ResourceBundle.getBundle(bundlename, locale);
String usernamePattern = bundle.getString("props_userNamePattern");
// ...
You can do that in the constructor of the validator. When used properly a new instance will be created for every view anyway.
Adding to the correct answer of BalusC; In JSF 2.0/2.1 Validators, Converters, PhaseListeners, etc are a kind of 'second-class' citizen as they are not injection targets.
This also means you can't inject an entity manager or an EJB, which can sometimes be used for validation purposes.
In JSF 2.2 this is supposed to change:
All JSF lifecycle artifacts should be
CDI-aware and support
injection/JSR-299/JSR-330
(PhaseListeners, NavHandlers,
Components, ActionListeners,
everything.)
See: http://jcp.org/en/jsr/detail?id=344
Perhaps seam-faces might help for this situation?
http://docs.jboss.org/seam/3/faces/latest/reference/en-US/html/artifacts.html
http://docs.jboss.org/seam/3/faces/latest/reference/en-US/html/faces.messages.html
This question is similar to:
jsf: integer property binded to a inputtext in UI is set to zero on submit
but I am not completely satisfied with the solution. The contexts is the same: I have a web form requiring an Integer value. If the textbox is left empty, I want my Integer field to be 'null' but instead the EL Parser automatically sets my id field to '0'.
I can fix the problem by setting a JVM Parameter in my local Tomcat VM:
-Dorg.apache.el.parser.COERCE_TO_ZERO=false
However, this will not work for our client's machine. Is it possible to set/change this JVM parameter "in-code".
Update: I've found that this is being requested but if anyone else has any other workaround, I would like to hear that too.
https://issues.apache.org/bugzilla/show_bug.cgi?id=48813
Update 2: I can't change the value back from a '0' to a 'null' because my application should treat '0' as an actual id. So I need to know at runtime whether the id textbox was left empty or not.
You can set the system properties programmatically using System#setProperty().
System.setProperty("org.apache.el.parser.COERCE_TO_ZERO", "false");
However, you need to ensure that this is been set before JSF/EL ever get initialized. Best place would be a ServletContextListener.
public class Config implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
System.setProperty("org.apache.el.parser.COERCE_TO_ZERO", "false");
}
#Override
public void contextDestroyed(ServletContextEvent event) {
// NOOP
}
}
Register it as <listener> in web.xml, or when you're already on Servlet 3.0 (Tomcat 7 and so), with #WebListener annotation.