Skip to content

Commit

Permalink
#4734: backport 2.3 changes into 3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
BalusC committed Feb 21, 2021
1 parent e329294 commit ccb398d
Show file tree
Hide file tree
Showing 6 changed files with 261 additions and 1 deletion.
Expand Up @@ -26,6 +26,7 @@
import com.sun.faces.util.MessageUtils;
import com.sun.faces.util.RequestStateManager;

import jakarta.el.PropertyNotFoundException;
import jakarta.el.ValueExpression;
import jakarta.faces.application.Application;
import jakarta.faces.component.UIComponent;
Expand Down Expand Up @@ -63,7 +64,23 @@ public Object getConvertedValue(FacesContext context, UIComponent component, Obj
}

if (null == converter && null != valueExpression) {
Class converterType = valueExpression.getType(context.getELContext());
Class converterType;
try {
converterType = valueExpression.getType(context.getELContext());
} catch (PropertyNotFoundException e) {
if (submittedValue == null) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE,
"Property of value expression {0} of component {1} could not be found, but submitted value is null in first place, so not attempting to convert",
new Object[]{
valueExpression.getExpressionString(),
component.getId() });
}
converterType = null; // See issue 4734.
} else {
throw e;
}
}
// if converterType is null, assume the modelType is "String".
if (converterType == null || converterType == Object.class) {
if (logger.isLoggable(Level.FINE)) {
Expand Down
@@ -0,0 +1,45 @@
/*
* Copyright (c) 1997, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020 Contributors to the Eclipse Foundation.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package com.sun.faces.test.javaee8.uiinput;

import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class Issue4734 implements Serializable {

private static final long serialVersionUID = 1L;

private Issue4734Entity entity;

@PostConstruct
public void init() {
entity = new Issue4734Entity(); // WARNING: unnatural approach, you'd expect that the converter would be used on f:viewParam, but it is part of the actual issue.
}

public Issue4734Entity getEntity() {
return entity;
}

public void setEntity(Issue4734Entity entity) {
this.entity = entity;
}
}
@@ -0,0 +1,58 @@
/*
* Copyright (c) 1997, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020 Contributors to the Eclipse Foundation.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package com.sun.faces.test.javaee8.uiinput;

import java.io.Serializable;
import java.util.Objects;

public class Issue4734Entity implements Serializable {

private static final long serialVersionUID = 1L;

private Long id;

public Issue4734Entity() {
//
}

public Issue4734Entity(Long id) {
this.id = id;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

@Override
public int hashCode() {
return Objects.hash(id);
}

@Override
public boolean equals(Object other) {
return other instanceof Issue4734Entity && Objects.equals(id, ((Issue4734Entity) other).id);
}

@Override
public String toString() {
return getClass().getSimpleName() + "[" + id + "]";
}
}
@@ -0,0 +1,39 @@
/*
* Copyright (c) 1997, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020 Contributors to the Eclipse Foundation.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package com.sun.faces.test.javaee8.uiinput;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;

@FacesConverter(forClass=Issue4734Entity.class)
public class Issue4734EntityConverter implements Converter {

@Override
public String getAsString(FacesContext context, UIComponent component, Object modelValue) {
Long id = modelValue == null ? null : ((Issue4734Entity) modelValue).getId();
return id == null ? "" : id.toString();
}

@Override
public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
Long id = submittedValue == null || submittedValue.isEmpty() ? null : Long.valueOf(submittedValue);
return id == null ? null : new Issue4734Entity(id);
}

}
39 changes: 39 additions & 0 deletions test/javaee8/uiinput/src/main/webapp/issue4734.xhtml
@@ -0,0 +1,39 @@
<!DOCTYPE html>
<!--
Copyright (c) 1997, 2019 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2020 Contributors to the Eclipse Foundation.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
http://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary
Licenses when the conditions for such availability set forth in the
Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
version 2 with the GNU Classpath Exception, which is available at
https://www.gnu.org/software/classpath/license.html.
SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
-->
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
>
<f:metadata>
<f:viewParam name="id" value="#{issue4734.entity.id}" />
</f:metadata>

<h:head>
<title>Issue4734 - f:viewParam should not throw "Target Unreachable, 'null' returned null" when below form is submitted at least twice.</title>
</h:head>

<h:body>
<h:form id="form">
<h:selectOneMenu value="#{issue4734.entity}">
<f:selectItem itemValue="#{null}" />
</h:selectOneMenu>
<h:commandButton id="submit" />
</h:form>
</h:body>
</html>
@@ -0,0 +1,62 @@
/*
* Copyright (c) 1997, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020 Contributors to the Eclipse Foundation.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package com.sun.faces.test.javaee8.uiinput;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.sun.faces.test.htmlunit.IgnoringIncorrectnessListener;
import com.sun.faces.test.junit.JsfTestRunner;

@RunWith(JsfTestRunner.class)
public class Issue4734IT {

private String webUrl;
private WebClient webClient;

@Before
public void setUp() {
webUrl = System.getProperty("integration.url");
webClient = new WebClient();
webClient.getOptions().setJavaScriptEnabled(true);
webClient.setJavaScriptTimeout(60000);
webClient.setIncorrectnessListener(new IgnoringIncorrectnessListener());
}

@Test
public void testIssue4734() throws Exception {
HtmlPage page = webClient.getPage(webUrl + "issue4734.xhtml");
HtmlSubmitInput submit = page.getHtmlElementById("form:submit");

submit.click(); // The first click is expected to work fine.

submit.click(); // Before the fix, the second click failed with com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException: 500 Internal Server Error

submit.click(); // A third one, just to be sure it keeps working! ;)
}

@After
public void tearDown() {
webClient.close();
}

}

0 comments on commit ccb398d

Please sign in to comment.