I am learning JSF Event Handling and when I try to run some sample code, I am getting a Null Pointer Exception.
This is my index.xhtml snippet,
<h:form>
<h2>Implement valueChangeListener</h2>
<hr />
<h:panelGrid columns="2">
Selected Locale:
<h:selectOneMenu value="#{userData.selectedCountry}" onchange="submit()">
<f:valueChangeListener type="com.cyb3rh4wk.test.LocaleChangeListener" />
<f:selectItems value="#{userData.countries}" />
</h:selectOneMenu>
Country Name:
<h:outputText id="countryInterface" value="#{userData.selectedCountry}" />
</h:panelGrid>
</h:form>
UserData.java
#ManagedBean(name = "userData", eager = true)
#ApplicationScoped
public class UserData implements Serializable{
private static Map<String, String> countryMap;
private String selectedCountry = "United Kingdom";
static {
countryMap = new LinkedHashMap<String, String>();
countryMap.put("en", "United Kingdon");
countryMap.put("fr", "French");
countryMap.put("de", "German");
countryMap.put("def", "Default");
}
public String getSelectedCountry() {
return selectedCountry;
}
public void setSelectedCountry(String selectedCountry) {
this.selectedCountry = selectedCountry;
System.out.println("Locale set");
}
public Map<String, String> getCountries() {
return countryMap;
}
public void localeChanged(ValueChangeEvent event) {
selectedCountry = event.getNewValue().toString();
}
}
LocaleChangeListener.java
public class LocaleChangeListener implements ValueChangeListener {
#Override
public void processValueChange(ValueChangeEvent event) throws AbortProcessingException {
UserData userData = (UserData) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("userData");
String newLocale = event.getNewValue().toString();
if (newLocale != null)
userData.setSelectedCountry(newLocale);
else
userData.setSelectedCountry("Default");
}
}
When I run these on Glassfish Server, I get an error,
java.lang.NullPointerException
at com.cyb3rh4wk.test.LocaleChangeListener.processValueChange(LocaleChangeListener.java:25)
at com.sun.faces.facelets.tag.jsf.core.ValueChangeListenerHandler$LazyValueChangeListener.processValueChange(ValueChangeListenerHandler.java:128)
at javax.faces.event.ValueChangeEvent.processListener(ValueChangeEvent.java:134)
Can anyone help me with this ?
You are getting NullPointerException because userData is not found in the session scope.
The reason this is happening is that you put the userData in the application scope (#ApplicationScoped annotation on your managed bean) and searching it in the session scope.
Eventhough you verified that userData is null it still prints Locale set because the bean is in the application scope as described in 2. above.
So what is the solution? Either change #ApplicationScoped to #SessionScoped or access your userData by changing:
UserData userData = (UserData) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("userData");
to
FacesContext ctx = FacesContext.getCurrentInstance();
UserData userData = (UserData)ctx.getExternalContext().getApplicationMap().get("userData");
Related
Are JSF converters supposed to be applied before validators? We have a situation where it seems it's being applied before the converter.
<o:importConstants
type="com.xxx.enums.UsState"
var="UsState" />
<b:selectOneMenu
id="homeStateSelectOneMenu"
value="#{contactPage.contact.homeState}"
label="Home State"
converter="DisplayableTextConverter">
<f:selectItem
id="selectOneUsStateSelectItem"
itemLabel="Select One"
noSelectionOption="true"
itemDisabled="true" />
<f:selectItems
id="usStateSelectItems"
value="#{UsState}" />
</b:selectOneMenu>
and the model object has this field:
#Enumerated(EnumType.STRING)
#Column(name = "home_state")
#NotNull //LYNCHPIN
private UsState homeState;
Converter:
#ApplicationScoped
#FacesConverter(value = "DisplayableTextConverter", managed = true)
public class DisplayableTextConverter implements Converter<DisplayableText> {
public static final String STATE_KEY = "DisplayableTextConverter.forClass";
#SuppressWarnings("unchecked")
#Override
public DisplayableText getAsObject(final FacesContext context, final UIComponent component, String text) {
text = trimToNull(text);
if (text != null) {
final String className = (String) component.getTransientStateHelper().getTransient(STATE_KEY);
try {
return DisplayableText.parseEnum(text, (Class<DisplayableText>) Class.forName(className));
} catch (final ClassNotFoundException e) {
throw new RuntimeException(e);
}
} else {
return null;
}
}
#Override
public String getAsString(final FacesContext context, final UIComponent component, final DisplayableText displayableText) {
if (displayableText != null) {
component.getTransientStateHelper().putTransient(STATE_KEY, displayableText.getClass().getName());
return displayableText.getDisplayText();
} else {
return null;
}
}
}
Enum: (truncated)
public enum UsState implements DisplayableText {
AL("Alabama"), AK("Alaska"), AZ("Arizona"), AR("Arkansas"), ....
public final String displayText;
#Override
public String getDisplayText() {
return displayText;
}
UsState(String specificDisplayValue) {
displayText = specificDisplayValue;
}
}
So what's interesting is if we remove #NotNull, the form submits, and if we add it, the submission fails. Looking at the stack trace, it appears that when the #NotNull it appears the validator is being called before the converter in certain cases. Why would this be?
Here is No #NotNull:
java.lang.IllegalArgumentException: Arkansas is not an instance of class com.xxx.UsState
at org.apache.bval.jsr.job.ValidateProperty.<init>(ValidateProperty.java:515)
at org.apache.bval.jsr.job.ValidationJobFactory.validateValue(ValidationJobFactory.java:76)
at org.apache.bval.jsr.ValidatorImpl.validateValue(ValidatorImpl.java:65)
at org.apache.bval.jsr.CascadingPropertyValidator.validateValue(CascadingPropertyValidator.java:99)
at javax.faces.validator.BeanValidator.validate(BeanValidator.java:218)
at javax.faces.component._ComponentUtils.callValidators(_ComponentUtils.java:291)
at javax.faces.component.UIInput.validateValue(UIInput.java:489)
at net.bootsfaces.component.selectOneMenu.SelectOneMenu.validateValue(SelectOneMenu.java:118)
at net.bootsfaces.component.selectOneMenu.SelectOneMenuRenderer.decode(SelectOneMenuRenderer.java:96)
at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:479)
at javax.faces.component.UIInput.decode(UIInput.java:371)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1408)
at javax.faces.component.UIInput.processDecodes(UIInput.java:207)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1402)
at javax.faces.component.UIForm.processDecodes(UIForm.java:154)
at org.apache.myfaces.context.servlet.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:775)
and here is without the #NotNull (breakpoint in DisplayableTextConverter):
at com.xxx.jsf.converter.DisplayableTextConverter.getAsObject(DisplayableTextConverter.java:21)
at com.xxx.jsf.converter.DisplayableTextConverter.getAsObject(DisplayableTextConverter.java:1)
at org.apache.myfaces.cdi.converter.FacesConverterCDIWrapper.getAsObject(FacesConverterCDIWrapper.java:63)
at net.bootsfaces.render.CoreRenderer.getConvertedValue(CoreRenderer.java:532)
at javax.faces.component.UIInput.getConvertedValue(UIInput.java:789)
at javax.faces.component.UIInput.validate(UIInput.java:708)
at javax.faces.component.UIInput.processValidators(UIInput.java:293)
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1458)
at javax.faces.component.UIForm.processValidators(UIForm.java:210)
at org.apache.myfaces.context.servlet.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:779)
Thanks! This is running on Apache TomEE 8.0.6 but with MyFaces 2.3.8, Bootsfaces 1.5.0
I am getting java.sql.SQLException: Missing IN or OUT parameter at index:: 2 error when trying to access a stored proc(created in oracle) which is having client name (varchar) as input param & cursor as output param. The error is coming when i test it thru a JSP page but when I tested the stroed proc thru a Junit i am not getting the error. So I am quite confused. Please find below my stored proc & also the DAOImpl class which is having the call. I can see that the JSP page is properly passing the name from a input text box to the name input param of stored proc.
PROCEDURE sp_get_client_details_by_name (
p_client_name IN ncr.ncr_parties.full_legal_name%TYPE,
p_result_set OUT SYS_REFCURSOR)
AS
BEGIN
OPEN p_result_set FOR
SELECT np.newedge_party_id AS client_id,
np.full_legal_name AS client_name,
np.city,
nc.name residence_country_name,
np.life_cycle_status AS status,
ec_addr.addr2 AS client_address1,
ec_addr.title_dist_compl AS client_address2,
ec_addr.zip AS client_address3,
ec_addr.state AS client_address4,
ec_addr.title_compl AS client_address_tc,
ec_addr.locality_compl AS client_address_lc,
le.newedge_legal_entity_id AS legal_entity_id,
le.full_legal_name AS legal_entity_name,
le_addr.addr2 AS legal_entity_address1,
le_addr.title_dist_compl AS legal_entity_address2,
le_addr.zip AS legal_entity_address3,
le_addr.state AS legal_entity_address4,
le_addr.title_compl AS legal_entity_address_tc,
le_addr.locality_compl AS legal_entity_address_lc
FROM ncr.ncr_parties np
JOIN ncr_legal_entities le
ON np.legal_entity_key = le.legal_entity_key
JOIN ncrglobalcountryview_vw nc
ON nc.country_alias_key = np.residence_country_aliases_key
JOIN ncr_cpty_addresses ec_addr
ON ec_addr.cpty_key = np.party_key
AND ec_addr.cpty_level = 'P'
AND ec_addr.addr_type_key = 1
JOIN ncr_cpty_addresses le_addr
ON le_addr.cpty_key = le.legal_entity_key
AND le_addr.cpty_level = 'LE'
AND le_addr.addr_type_key = 1
WHERE np.full_legal_name LIKE '%' || p_client_name || '%';
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (
SQLERRM || ' backtrace: ' || DBMS_UTILITY.format_error_backtrace);
raise_application_error (
'-20000',
'Unknown exception occurred. Please contact support.' || SQLERRM);
END sp_get_client_details_by_name;
END pkg_ocr_gui;
public class ECIDDetailsDAOImpl implements ECIDDetailsDAO {
private DataSource dataSource;
private static final String SP_GET_ECID_DETAILS = "ncr.pkg_ocr_gui.sp_get_client_details_by_name";
private static final String EC_ID_NAME_PARAM = "p_client_name";
private static final String ECID_CUR_TYPES = "p_result_set";
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public List<ECIDDetails> getECIDDetails(String elementaryClientName) {
GetECIDDetailsStoredProcedure getECIDDetailsStoreProc = new GetECIDDetailsStoredProcedure(dataSource, SP_GET_ECID_DETAILS);
Map<String, Object> resultsMap = getECIDDetailsStoreProc.executeECIDetails(elementaryClientName);
List<ECIDDetails> ecidDetails = (List<ECIDDetails>) resultsMap.get(ECID_CUR_TYPES);
return ecidDetails;
}
class GetECIDDetailsStoredProcedure extends StoredProcedure {
public GetECIDDetailsStoredProcedure(DataSource dataSource, String sprocName) {
super(dataSource, sprocName);
declareParameter(new SqlParameter(EC_ID_NAME_PARAM, java.sql.Types.VARCHAR));
declareParameter(new SqlOutParameter(ECID_CUR_TYPES, OracleTypes.CURSOR, new BeanPropertyRowMapper<ECIDDetails>(ECIDDetails.class)));
compile();
}
public Map<String, Object> executeECIDetails(String elementaryClientName) {
Map <String, Object> inputs = new HashMap<String, Object>();
inputs.put(EC_ID_NAME_PARAM, elementaryClientName);
return super.execute(inputs);
}
}
}
Below is my JUnit test which is giving back proper data
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath*:test-applicationcontext.xml"})
public class ECIDFetchServiceTest {
#Autowired
ECIDDetailsDAOImpl ecIDDAO;
#Test
public void validategetECIDDetails() {
List<ECIDDetails> ecidDetails = new ArrayList<ECIDDetails>();
ecidDetails = ecIDDAO.getECIDDetails("ABN");
assertNotNull(ecidDetails);
assertTrue(ecidDetails.size() > 0);
}
}
Hi Priyesh,
I am using JSF to create the UI. Please find below the necessary codes.
JSF Code
<h:panelGrid columns="3" cellspacing="5" cellpadding="5">
<h:outputLabel value="Elementary Client Name" />
<h:inputText value="#{ecIDBean.elementaryClientName}" />
<h:commandButton value="Get EC" action="#{ecIDBean.executeEcIDList}">
</h:commandButton>
</h:panelGrid>
Managed Bean Class
public class ECIDFetchBean {
private String elementaryClientName;
private List<ECIDDetails> ecIDList;
private ECIDFetchService ecIDFetchService;
public ECIDFetchBean() {
ApplicationContext ctx = ApplicationContextProvider.getApplicationContext();
ecIDFetchService = (ECIDFetchServiceImpl)ctx.getBean("ecIDFetchService");
}
public String getElementaryClientName() {
return elementaryClientName;
}
public void setElementaryClientName(String elementaryClientName) {
this.elementaryClientName = elementaryClientName;
}
public List<ECIDDetails> getEcIDList() {
return ecIDList;
}
public void setEcIDList(List<ECIDDetails> ecIDList) {
this.ecIDList = ecIDList;
}
public void executeEcIDList() {
ecIDList = ecIDFetchService.getECIDDetails(elementaryClientName);
}
}
Service Class
public class ECIDFetchServiceImpl implements ECIDFetchService {
private ECIDDetailsDAO ecidDetailsDAO;
public List<ECIDDetails> getECIDDetails(String elementaryClientName) throws OCRReportingException {
return ecidDetailsDAO.getECIDDetails(elementaryClientName);
}
Hi Priyesh,
JSP is also pointing to same Database. I changed my DAOImpl class to call stored proc using
SimpleJdbcCall & it's working fine now from both JUnit as well as JSP.
public List<ECIDDetails> getECIDDetailsBySimpleJDBCCall(String elementaryClientName){
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(dataSource);
simpleJdbcCall.withCatalogName("ncr.pkg_ocr_gui").withProcedureName("sp_get_client_details_by_name")
.withoutProcedureColumnMetaDataAccess()
.declareParameters(new SqlParameter(EC_ID_NAME_PARAM, java.sql.Types.VARCHAR),
new SqlOutParameter(ECID_CUR_TYPES, OracleTypes.CURSOR, new BeanPropertyRowMapper<ECIDDetails>(ECIDDetails.class)));
MapSqlParameterSource sqlParameterSource = new MapSqlParameterSource();
sqlParameterSource.addValue(EC_ID_NAME_PARAM, elementaryClientName);
Map<String, Object> results = simpleJdbcCall.execute(sqlParameterSource);
List<ECIDDetails> ecidDetails = (List<ECIDDetails>) results.get(ECID_CUR_TYPES);
return ecidDetails;
}
I'm using Hibernate + JSF + PrimeFaces. Now I wanna update password of admin but I always get error dialog. I can't figure out what wrong in my code. Hope anyone suggest me.
loginBean (SessionScoped)
public class loginBean {
private Users username;
private UsersDao userdao;
/** Creates a new instance of loginBean */
public loginBean() {
userdao = new UsersDao();
username = new Users();
}
public Users getUsername() {
return username;
}
public void setUsername(Users username) {
this.username = username;
}
public void updateUser(){
String msg;
if(userdao.updateUser(username)){
msg = "Updated Successfully!";
}else{
msg = "Error. Please check again!";
}
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, null);
FacesContext.getCurrentInstance().addMessage(msg, message);
}
}
UserDAO.java
public class UsersDao {
public boolean updateUser(Users user){
boolean flag;
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
try{
session.beginTransaction();
session.save(user);
session.beginTransaction().commit();
flag = true;
}catch(Exception e){
flag = false;
session.beginTransaction().rollback();
}
return flag;
}
}
xhtml
<p:growl id="growl" showDetail="true" life="3000" />
<h:form id="tab">
<h:outputLabel>Password</h:outputLabel>
<h:inputSecret value="#{loginBean.username.password}" />
<p:commandButton id="loginButton" value="Login" update=":growl" ajax="false" action="#{loginBean.updateUser}"/>
</h:form>
You're actually performing a save operation into the Session, instead of an update one, that's why you've got a Violation of PRIMARY KEY exception. You're telling Hibernate to add a new user with the same credentials, which is constrained by the Data Base.
In addition, and unrelated to the concrete problem, you should change your Users class name to User, as it refers to a concrete user.
i want that, when user select item in a inputText field populates with data from database.
I have a select menu list:
<h:selectOneMenu id="blah" value="#{controller.selected.id}" title="#{bundle.CreateTitle_id}" >
<f:selectItems value="#{controller.listOfId()}" />
</h:selectOneMenu>
and let's say have input text like this:
<h:inputText value="In here we place value from backing bean"></h:inputText>
How can i make after selecting an item from a list(which holds the id) populate text field with other data from my backing bean(let's say a name).
Here is my backingBean:
#ManagedBean(name = "controller")
#SessionScoped
public class Bean implements Serializable {
private Catalog current;// here i'm holding int id, String name and other stuff...
private DataModel items = null;
#EJB
private probaSession.CatalogFacade ejbFacade;
private PaginationHelper pagination;
private int selectedItemIndex;
public KatalogController() {
}
public Katalog getSelected() {
if (current == null) {
current = new Catalog();
selectedItemIndex = -1;
}
return current;
}
private KatalogFacade getFacade() {
return ejbFacade;
}
public PaginationHelper getPagination() {
if (pagination == null) {
pagination = new PaginationHelper(10) {
#Override
public int getItemsCount() {
return getFacade().count();
}
#Override
public DataModel createPageDataModel() {
return new ListDataModel(getFacade().findRange(new int[]{getPageFirstItem(), getPageFirstItem() + getPageSize()}));
}
};
}
return pagination;
}
//......
public ArrayList<Catalog> listOfId() {
ArrayList<Catalog> list=new ArrayList<Catalog>();
try{
String upit="select id from Catalog";
Statement st=connection.createStatement();
ResultSet rs=st.executeQuery(upit);
while(rs.next()) {
Katalog k=new Katalog();
k.setId(rs.getInt(1));
k.setName(rs.getString(2));
list.add(k);
}
disconnect();
}
catch (Exception ex) {
ex.printStackTrace();
}
return list;
}
and that's pretty much it.
I'm here if anything needs to explaining. It think it is easy(using ajax let's say) but i don't even know how to start doing it...
You must add an f:ajax (that is standard, many component library offer extended versions) to catch a change event in the inputText
<h:selectOneMenu id="blah" value="#{controller.selected.id}" title="#{bundle.CreateTitle_id}" >
<f:selectItems value="#{controller.listOfId()}" />
<f:ajax
event="change" <-- The event to capture. I believe that if not specified
there is a default event to capture from
each component (for inputText it would be "change")
render="myForm:foo" <-- Only repaint "blah"
listener="#{controller.myBlahListener}"
</h:selectOneMenu>
<h:inputText id="foo" value="#{controller.fooText}"/>
Your listener will read the new value in this.getSelected().getId(), and change the model so that controller.getFooText() returns the new value (the easiest way probably is this.setFooTest(this.getSelected().getId(), but that depends of your model.
EDIT
Finally figured it out. You need to add this to your project. Probably a good thing to document:
http://www.jqplot.com/
No chart is displaying on the page, even though the code of the javascript etc is available through Firebug.
I am using Mojarra and Primefaces 3
<h:form>
<p:growl id="growl" showDetail="true" />
<p:pieChart value="#{distributionChart.pieModel}" legendPosition="w"
title="Interactive Pie Chart" style="width:400px;height:300px">
<p:ajax event="itemSelect" listener="#{distributionChart.itemSelect}" update="growl" />
</p:pieChart>
</h:form>
Backing bean
#Named
#RequestScoped
public class DistributionChart implements Serializable {
#Inject
private QuestionServiceBean questionService;
private CartesianChartModel categoryModel;
private PieChartModel pieModel;
private List<QuestionCategoryDistribution> distribution;
#PostConstruct
public void init() {
distribution = questionService.getQuestionCategoryDistribution();
createPieModel();
}
public void itemSelect(ItemSelectEvent event) {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Item selected",
"Item Index: " + event.getItemIndex() + ", Series Index:" + event.getSeriesIndex());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public PieChartModel getPieModel() {
return pieModel;
}
private void createPieModel() {
pieModel = new PieChartModel();
for (QuestionCategoryDistribution obj : distribution) {
pieModel.set(obj.getCategoryDescription(), obj.getNumberOfQuestions());
}
}
}