Input field not updating
This is the complete source code: http://www.sendspace.com/file/lwxpyf
I have a problem with a JSF page that I am unable to resolve. I have a JSF page that is used to store application settings in a database table. This is the source code for the JSF page:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<ui:insert name="header">
<ui:include src="header.xhtml"/>
</ui:insert>
</h:head>
<h:body>
<h1><img src="resources/css/images/icon.png" alt="NVIDIA.com" /> Settings Center</h1>
<!-- layer for black background of the buttons -->
<div id="toolbar" style="margin: 0 auto; width:1180px; height:30px; position:relative; background-color:black">
<!-- Include page Navigation -->
<ui:insert name="Navigation">
<ui:include src="Navigation.xhtml"/>
</ui:insert>
</div>
<div id="greenBand" class="ui-state-default ui-corner-allh" style="position:relative; top:35px; left:0px;">
<h:graphicImage alt="Application Settings" style="position:relative; top:-20px; left:9px;" value="resources/images/logo_application_settings.png" />
</div>
<div id="main" style="margin: 0 auto; width:1190px; height:700px; position:absolute; background-color:transparent; top:105px">
<div id="mainpage" style="margin: 0 auto; width:1190px; height:500px; position:absolute; background-color:transparent; top:80px">
<h:form>
<div id="settingsdiv" style="width:550px; height:400px; position:absolute; background-color:r; top:20px; left:1px">
<h:panelGrid columns="2">
<h:panelGroup>User Session Timeout</h:panelGroup>
<h:panelGroup>
<h:selectOneMenu value="#{ApplicationController.settings['SessionTTL']}">
<f:selectItem itemValue="#{ApplicationController.settings['SessionTTL']}" itemLabel="#{ApplicationController.settings['SessionTTL']}" />
<f:selectItem itemValue="two" itemLabel="Option two" />
<f:selectItem itemValue="three" itemLabel="Option three" />
<f:selectItem itemValue="custom" itemLabel="Define custom value" />
<f:ajax render="input" />
</h:selectOneMenu>
<h:panelGroup id="input">
<h:inputText value="#{ApplicationController.settings['SessionTTL']}" rendered="#{ApplicationController.settings['SessionTTL'] == 'custom'}" required="true" />
</h:panelGroup>
</h:panelGroup>
<h:panelGroup>Maximum allowed users</h:panelGroup>
<h:panelGroup>
<h:selectOneMenu value="#{ApplicationController.settings['MaxUsersActive']}">
<f:selectItem itemValue="#{ApplicationController.settings['MaxUsersActive']}" itemLabel="#{ApplicationController.settings['MaxUsersActive']}" />
<f:selectItem itemValue="two" itemLabel="Option two" />
<f:selectItem itemValue="three" itemLabel="Option three" />
<f:selectItem itemValue="custom" itemLabel="Define custom value" />
<f:ajax render="inputl" />
</h:selectOneMenu>
<h:panelGroup id="inputl">
<h:inputText value="#{ApplicationController.settings['MaxUsersActive']}" rendered="#{ApplicationController.settings['MaxUsersActive'] == 'custom'}" required="true" />
</h:panelGroup>
</h:panelGroup>
</h:panelGrid>
</div>
<div id="settingsonediv" style="width:350px; height:400px; position:absolute; background-color:transparent; top:20px; left:400px">
</div>
<div id="settingstwodiv" style="width:150px; height:60px; position:absolute; background-color:transparent; top:380px; left:800px">
<h:commandButton value="Save Settings" action="#{ApplicationController.updateDBSettings}">
<f:ajax render="@form" execute="@form"></f:ajax>
</h:commandButton>
</div>
</h:form>
</div>
</div>
</h:body>
</html>
And this is the managed bean:
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
// or import javax.faces.bean.SessionScoped;
import javax.inject.Named;
/* include SQL Packages */
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import javax.annotation.Resource;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
// or import javax.faces.bean.ManagedBean;
import org.glassfish.osgicdi.OSGiService;
@Named("ApplicationController")
@SessionScoped
public class Application implements Serializable {
/* This Hash Map will be used to store setting and value */
private HashMap<String, String> settingsMap = null;
public Application(){
}
/* Call the Oracle JDBC Connection driver */
@Resource(name = "jdbc/Oracle")
private DataSource ds;
/* Hash Map
* Send this hash map with the settings and values to the JSF page
*/
public HashMap<String, String> getsettings(){
return settingsMap;
}
/* Get a Hash Map with settings and values. The table is genarated right
* after the constructor is initialized.
*/
@PostConstruct
public void initSettings() throws SQLException
{
settingsMap = new HashMap<String, String>();
if(ds == null) {
throw new SQLException("Can't get data source");
}
/* Initialize a connection to Oracle */
Connection conn = ds.getConnection();
if(conn == null) {
throw new SQLException("Can't get database connection");
}
/* With SQL statement get all settings and values */
PreparedStatement ps = conn.prepareStatement("SELECT * from GLOBALSETTINGS");
try
{
//get data from database
ResultSet result = ps.executeQuery();
while (result.next())
{
settingsMap.put(result.getString("SettingName"), result.getString("SettingValue"));
}
}
finally
{
ps.close();
conn.close();
}
}
/* JSF returns the updated values into the HashMap */
/* Update Settings Values */
public void updateDBSettings() throws SQLException {
String SQL_Statement = null;
if (ds == null) throw new SQLException();
Connection conn = ds.getConnection();
if (conn == null) throw new SQLException();
try {
conn.setAutoCommit(false);
boolean committed = false;
try {
/* Insert the new settings values with one SQL statement */
SQL_Statement = "UPDATE GLOBALSETTINGS " +
"SET \"SettingValue\" = " +
"CASE " +
"WHEN \"SettingName\" = 'SessionTTL' THEN ? " +
"WHEN \"SettingName\" = 'MaxUsersActive' THEN ? " +
"END " +
"WHERE \"SettingName\" IN ('SessionTTL', 'MaxUsersActive')";
/* Exete thre SQL statement */
PreparedStatement updateQuery = conn.prepareStatement(SQL_Statement);
updateQuery.setString(1, settingsMap.get("SessionTTL"));
updateQuery.setString(2, settingsMap.get("MaxUsersActive"));
updateQuery.executeQuery();
conn.commit();
committed = true;
} finally {
if (!committed) conn.rollback();
}
}
finally {
/* Release the resource after all SQL queries are executed */
conn.close();
}
/* Refresh Hash Map
* Get again settings from Oracle
*/
initSettings();
}
}
This is the problem I am facing:
When I open the JSF page I get this menu:
Then I select custom from the menu:
I am getting this input box next to the menu:
Then I enter the custom value from the keyboard:
But when I click the Save button I get this. I can see that the database field is updating but the values are "custom"
When I enter the same two values, I get this:
It seems to me that when I click custom
and I enter a custom value, the HashMap is not updated. The weird thing is that when I do it again the HashMap is updated and the value is correct. How can I solve this problem?
Best regards
EDIT
I suspect the JSF version is causing this issue. This contentfaces-config.xml
<?xml version="1.0"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<managed-bean>
<description>comment</description>
<managed-bean-name>ApplicationController</managed-bean-name>
<managed-bean-class>com.DX_57.SM_57.Application</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>comment</description>
<managed-bean-name>DashboardController</managed-bean-name>
<managed-bean-class>com.DX_57.SM_57.Dashboard</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>comment</description>
<managed-bean-name>DatabaseController</managed-bean-name>
<managed-bean-class>com.DX_57.SM_57.Database</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>comment</description>
<managed-bean-name>GeneralController</managed-bean-name>
<managed-bean-class>com.DX_57.SM_57.General</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>comment</description>
<managed-bean-name>GlassfishController</managed-bean-name>
<managed-bean-class>com.DX_57.SM_57.Glassfish</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>comment</description>
<managed-bean-name>LinuxController</managed-bean-name>
<managed-bean-class>com.DX_57.SM_57.Linux</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>comment</description>
<managed-bean-name>LinuxConfigurationController</managed-bean-name>
<managed-bean-class>com.DX_57.SM_57.LinuxConfiguration</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>comment</description>
<managed-bean-name>LogController</managed-bean-name>
<managed-bean-class>com.DX_57.SM_57.Log</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>comment</description>
<managed-bean-name>OracleController</managed-bean-name>
<managed-bean-class>com.DX_57.SM_57.Oracle</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>comment</description>
<managed-bean-name>UpdatesController</managed-bean-name>
<managed-bean-class>com.DX_57.SM_57.Updates</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
</faces-config>
This content beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
This content web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
How do I change them to use the latest JSF?
EDIT 2 I have disabled JavaScript in Firefox. I checked the code. It turns out it works, but I hit the Save button every time:
I choose a custom one and click the "Save" button
When I click the Save button, a custom field appears.
When you enter a custom value and click Save, the field is updated.
I suppose it won't work because no data is sent from JavaScrips to the server
EDIT 3 Debug info from firebug:
I choose from the custom menu:
<update id="j_idt5:input"><![CDATA[<span id="j_idt5:input"><input type="text" name="j_idt5:j_idt15" value="custom" /></span>]]></update>
I am printing a custom value:
<?xml version='1.0' encoding='UTF-8'?>
<partial-response><changes><update id="j_idt5"><![CDATA[
<form id="j_idt5" name="j_idt5" method="post" action="/SM_57-1.0-SNAPSHOT/Application.jsf" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="j_idt5" value="j_idt5" />
<table>
<tbody>
<tr>
<td>User Session Timeout</td>
<td><select id="j_idt5:j_idt10" name="j_idt5:j_idt10" size="1" onchange="mojarra.ab(this,event,'valueChange',0,'j_idt5:input')"> <option value="custom" selected="selected">custom</option>
<option value="two">Option two</option>
<option value="three">Option three</option>
<option value="custom" selected="selected">Define custom value</option>
</select><span id="j_idt5:input"><input type="text" name="j_idt5:j_idt15" value="custom" /></span></td>
</tr>
<tr>
<td>Maximum allowed users</td>
</tr>
</tbody>
</table>
<input id="j_idt5:j_idt18" type="submit" name="j_idt5:j_idt18" value="Save Settings" onclick="mojarra.ab(this,event,'action','@form','@form');return false" />
</form>]]></update><update id="javax.faces.ViewState"><![CDATA[-8356663926661541536:7758149566419150570]]></update></changes></partial-response>
I click the save button:
<?xml version='1.0' encoding='UTF-8'?>
<partial-response><changes><update id="j_idt5"><![CDATA[
<form id="j_idt5" name="j_idt5" method="post" action="/SM_57-1.0-SNAPSHOT/Application.jsf" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="j_idt5" value="j_idt5" />
<table>
<tbody>
<tr>
<td>User Session Timeout</td>
<td><select id="j_idt5:j_idt10" name="j_idt5:j_idt10" size="1" onchange="mojarra.ab(this,event,'valueChange',0,'j_idt5:input')"> <option value="wdwdew" selected="selected">wdwdew</option>
<option value="two">Option two</option>
<option value="three">Option three</option>
<option value="custom">Define custom value</option>
</select><span id="j_idt5:input"></span></td>
</tr>
<tr>
<td>Maximum allowed users</td>
</tr>
</tbody>
</table>
<input id="j_idt5:j_idt18" type="submit" name="j_idt5:j_idt18" value="Save Settings" onclick="mojarra.ab(this,event,'action','@form','@form');return false" />
</form>]]></update><update id="javax.faces.ViewState"><![CDATA[-8356663926661541536:7758149566419150570]]></update></changes></partial-response>
source to share
You have overridden beans in faces-config.xml
. Your managed bean is overridden as a scope with a request:
<managed-bean>
<description>comment</description>
<managed-bean-name>ApplicationController</managed-bean-name>
<managed-bean-class>com.DX_57.SM_57.Application</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
Managed bean configurations in the file faces-config.xml
take precedence over annotations. Your ApplicationController
bean is actually thus a JSF request-driven bean, not a session-driven CDI bean as the annotations announced. A new one will be created on every ajax request. All changes made in previous requests are "forgotten".
You have 2 options:
- Remove the bean config from
faces-config.xml
. - Change the control scope of the bean to
view
(note that it will still be JSF that manages the bean instance, not CDI, and that CDI has no suitable annotation@ViewScoped
).
source to share
try adding f:ajax
so that your data inside the form is submitted to the server
replace your save btn with this
<h:commandButton value="Save Settings" action="#{applicationController.updateDBSettings}">
<f:ajax render="@form" execute="@form"></f:ajax>
</h:commandButton>
to see where the problem is: try removing the call initSettings()
from the end of updateDBSettings (), or make sure reinitialization fills the map with the appropriate values ...
Edit:
Open the app in Chrome and press F12, in dev tools go to the "Scripts" tab and then right below it you will see all the js files that are loaded, do you see any suspicious "libraries" in there? try removing it from your wen pages ... to see what is the cause of the error in FF
source to share