My custom exception handler is not being invoked by the container to intercept (checked or unchecked) exceptions (I verified it through the debugger). I have this Entity bean class with #Email annotation for the email field, and when the user types in an invalid email through the JSF page, an error message is being displayed, however, the error message is not the one I set through the custom exception handler class, rather it is the one I have set as the default message for the #Email annotation. The error message generated by the custom exception handler has a prefix string "Exception caught by the custom Exception handler: ". I surmise that an invalid email should throw a ConstraintViolationException, which would be an ideal case for the exception handler to catch.
The JSF page allows the user information to be updated, so when I update the user's email with an invalid one and click the "Update" CommandButton, the registered action method is not being invoked (I verified it through the debugger). Furthermore, what I don't seem to figure out, is that when the "invalid email" error message is displayed on the JSF page, the "Add User" command Button gets disabled, so I can not navigate to the "Add User" JSF page. Any idea, why the exception handler and the page navigation (Add User) are not working in case of an error?
public class CustomExceptionHandler extends ExceptionHandlerWrapper {
private ExceptionHandler wrapped;
private final static Logger logger = Logger.getLogger(CustomExceptionHandler.class.getName());
public CustomExceptionHandler(ExceptionHandler w) {
wrapped = w;
}
#Override
public ExceptionHandler getWrapped() {
return wrapped;
}
#Override
public void handle() throws FacesException {
Iterator iterator = getUnhandledExceptionQueuedEvents().iterator();
while (iterator.hasNext()) {
ExceptionQueuedEvent event = (ExceptionQueuedEvent) iterator.next();
ExceptionQueuedEventContext context = (ExceptionQueuedEventContext)event.getSource();
Throwable throwable = context.getException();
FacesContext fc = FacesContext.getCurrentInstance();
try {
Flash flash = fc.getExternalContext().getFlash();
// Put the exception in the flash scope to be displayed in the error
// page if necessary ...
String errorMessage = "Exception caught by the custom Exception handler: "+throwable.getMessage();
logger.severe(errorMessage);
flash.put("errorDetails", errorMessage);
NavigationHandler navigationHandler = fc.getApplication().getNavigationHandler();
//navigationHandler.handleNavigation(fc, null, "/loginmanagement");
navigationHandler.handleNavigation(fc, null, "error?faces-redirect=true");
fc.renderResponse();
} finally {
iterator.remove();
}
}
// Let the parent handle the rest
getWrapped().handle();
}
}
The factory class:
public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory {
private ExceptionHandlerFactory parent;
public CustomExceptionHandlerFactory(ExceptionHandlerFactory parent) {
this.parent = parent;
}
#Override
public ExceptionHandler getExceptionHandler() {
ExceptionHandler result = new CustomExceptionHandler(parent.getExceptionHandler());
return result;
}
}
The faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.3"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_3.xsd">
<application>
<resource-bundle>
<base-name>webmessages</base-name>
<var>bundle</var>
</resource-bundle>
<locale-config>
<default-locale>en</default-locale>
<!-- <supported-locale>es</supported-locale> -->
</locale-config>
</application>
<error-page>
<exception-type>java.lang.RuntimeException</exception-type>
<location>/loginmanagement.xhtml</location>
</error-page>
<factory>
<exception-handler-factory>
org.me.mavenlistservicedb.applicationexception.CustomExceptionHandlerFactory
</exception-handler-factory>
</factory>
</faces-config>
Here is the relevant excerpt of the JSF page
<h:column>
<f:facet name="header">#{bundle.loginmanagementemail}</f:facet>
<h:inputText value = "#{l.email}"
size ="30" rendered = "#{l.canUpdate}" />
<h:outputText value = "#{l.email}"
rendered = "#{not l.canUpdate}" />
</h:column>
<f:facet name="footer">
<h:panelGroup style="display: block; border-color: aquamarine;text-align: center;">
<h:commandButton id="update"
value="Save updates"
action="#{loginManagment.saveUpdate}" />
<h:commandButton id="add"
value="Add User"
action="adduser" />
</h:panelGroup>
</f:facet>
I use Netbeans on Windows 10 with Glassfish 5.1.
Thanks
I have :
- Repository Class:
#SessionScoped
public class EmployeeRepository {
#PersistenceContext
EntityManager entityManager;
public List<Employee> getEmployees(){
TypedQuery<Employee> qu = entityManager.createQuery("select * from Employee", Employee.class);
List<Employee> emp2 = qu.getResultList();
return emp2;
}
}
and
Managed Bean:
#ManagedBean(name = "helloWorldBean")
public class HelloWorldBean {
#Inject
private EmployeeRepository employeerepo;
public String getMsg() {
return "Hallo";
}
public String getEmployees() {
return String.valueOf(employeerepo.getEmployees().size());
}
}
and a JSF Page:
<h:head>
<title>JavaCodeGeeks</title>
</h:head>
<h:body>
- Message : <h:outputText value="#{helloWorldBean.msg}" />
- Employee count : <h:outputText value="#{helloWorldBean.employees}" />
</h:body>
</html>
I have an beans.xml in my META-INF Folder (src\META-INF) without special configurations:
<?xml version="1.0"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all" version="1.1">
</beans>
Problem:
Page throws nullpointer exception, because the EmployeeRepository is not injected in the HelloWorldBean.
What to do to be able to inject Instances of classes in my case ?
As you are using CDI, you should not be using #ManagedBean (which is a JSF annotation). While I have actually seen this working, most implementations will not allow you to inject a CDI bean into a classic JSF bean.
To allow for CDI injection in JSF beans, the CDI specification allows you to define JSF backing beans by specifying the #Named annotation in combination with a scope (#RequestScoped, #javax.faces.view.ViewScoped, #SessionScoped and #ApplicationScoped).
So in summary, the following piece of code should solve your problem,
#Named
#RequestScoped
public class HelloWorldBean {
#Inject
private EmployeeRepository employeerepo;
public String getMsg() {
return "Hallo";
}
public String getEmployees() {
return String.valueOf(employeerepo.getEmployees().size());
}
}
You can also read up further on the topic via some old Q/A's here on the site,
How to inject a CDI Bean in a ManagedBean?
#ManagedProperty does not work in a CDI managed bean
CDI beans injection
This question already has answers here:
creating a simple link that invokes a jsf method
(1 answer)
Localization in JSF, how to remember selected locale per session instead of per request/view
(5 answers)
Closed 5 years ago.
I was trying to include translations in my website, german and english. Sadly i seem to be to stupid to do it right and can't spot the problem. Can someone tell my why my language wont load? It always sticks with the default language.properties file and wont change to language_de / language_en
Here is my faces-config
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
<application>
<locale-config>
<default-locale>de</default-locale>
<supported-locale>en</supported-locale>
</locale-config>
<resource-bundle>
<base-name>language</base-name>
<var>language</var>
</resource-bundle>
</application>
</faces-config>
Here is my project structure
Here is the component i use to change the language
<p:link id="buttonHeader_languageLink">
<p:graphicImage id="buttonHeader_languageIcon"
value="#{languageBean.currentLanguage.graphicPath}"
onclick="#{languageBean.changeLanguage()}"></p:graphicImage>
</p:link>
and my ManagedBean
#ManagedBean
#SessionScoped
public class LanguageBean implements Serializable {
private static final long serialVersionUID = 1L;
private final static SessionLanguage GERMAN = new SessionLanguage(new Locale("de"), "/resource/image/german.png");
private final static SessionLanguage ENGLISH = new SessionLanguage(new Locale("en"), "/resource/image/english.png");
private SessionLanguage currentLanguage = GERMAN;
public SessionLanguage getCurrentLanguage() {
return currentLanguage;
}
public void changeLanguage() {
if(currentLanguage.equals(GERMAN)){
currentLanguage = ENGLISH;
}else{
currentLanguage = GERMAN;
}
FacesContext.getCurrentInstance().getViewRoot().setLocale(currentLanguage.getLocale());
}
}
And this is the response header after clicking the link which seems to be missing the language :/
I am new to JSF (Have Fair knowledge in Struts) have tried some examples of JSF from internet and i have some doubts regarding the flow.
The example is some thing like below
Login.xhtml
<div>
<h:panelGrid columns="2">
<h:outputText value="Name"></h:outputText>
<h:inputText value="#{loginBean.name}"></h:inputText>
<h:outputText value="Password"></h:outputText>
<h:inputSecret value="#{loginBean.password}"></h:inputSecret>
<h:commandButton value="Login" action="login"></h:commandButton>
</h:panelGrid>
</div>
faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>
<managed-bean-name>loginBean</managed-bean-name>
<managed-bean-class>com.tutorial.LoginBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<navigation-rule>
<display-name>template/Login.xhtml</display-name>
<from-view-id>/template/Login.xhtml</from-view-id>
<navigation-case>
<from-outcome>login</from-outcome>
<to-view-id>/template/Welcome.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
LoginBean:
package com.tutorial;
public class LoginBean
{
private String name;
private String password;
public String getName ()
{
return name;
}
public void setName (final String name)
{
this.name = name;
}
public String getPassword ()
{
return password;
}
public void setPassword (final String password)
{
this.password = password;
}
}
Flow is that in login page we will give username and password and it will go to welcome page and will display the name
Listing out my queries below PLEASE help me in to figuer these things and get a better understanding of JSF
In struts we will have code something like below
<action path="/LoginAction" type="com.app.action.LoginAction" name="LoginForm">
so for this "LoginAction" it will go to the LoginAction class and the bean or DTO will be LoginForm. in the above faces-config.xml the login.jsp is not linked to any bean class.
In struts we have execute method. do we have any default method in JSF like that ?
In JSF if we have a requirement like "when we click on a button in JSP the control should go to a java class and based on authentication in java we will go the success or failure page". what should be the configaration in faces-config.xml? in <navigation> tag ther is only tag with <to-view> (which means a JSP to my understanding) what should we do if the control should go to java class.
in the above faces-config.xml the login.jsp is not linked to any bean class.
I'm not sure why that's necessary. JSF is component based, not request based.
In struts we have execute method. do we have any default method in JSF like that ?
Nope, you've the full freedom to bind the action attribute of a command component to any arbitrary method of the backing bean.
E.g.
<h:commandButton value="Login" action="#{loginBean.submit}" />
with
public String submit() {
// Do your thing here.
// ...
return "login";
}
Note that the method name is fully free to your choice. You can also use #{loginBean.login} with a public String login() method. I'm not sure why you would be restricted to a single predefined action name. JSF is component based, not request based.
"when we click on a button in JSP the control should go to a java class and based on authentication in java we will go the success or failure page". what should be the configaration in faces-config.xml? in tag ther is only tag with (which means a JSP to my understanding) what should we do if the control should go to java class.
Create another <navigation-case>
<navigation-case>
<from-outcome>error</from-outcome>
<to-view-id>/template/Error.xhtml</to-view-id>
</navigation-case>
and handle accordingly in the action method:
public String submit() {
// Do your thing here.
// ...
if (success) {
return "login";
} else {
return "error";
}
}
Noted should be that navigation cases are soo JSF 1.x. On JSF 2.x they are not necessary anymore. Just get rid of the whole <navigation-rule> block in faces-config.xml and make use of JSF implicit navigation feature.
if (success) {
return "/template/Welcome";
} else {
return "/template/Error";
}
See also:
Communication in JSF 2.0
I want to use Primefaces ThemeSwitcher. I'm interested how I can save the selected theme when I reload the web application. For example how I can set the theme name as variable from database?
You won't be needing the ThemeSwitcher to effect the kind of persistence you're looking for.
Simply perform the database lookup for the theme in a ServletContextListener and then store the value in the servlet context, possibly overriding whatever you've set in the web.xml
public Class MyContextListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent sce){
String selectedTheme = myThemeDAO.getConfiguredTheme();
sce.getServletContext().setInitParameter("primefaces.THEME",selectedTheme);
}
}
link your ThemeSwitcher component to a managedBean and add a listener linked to a ajax event:
<h:form id="form-theme">
<p:themeSwitcher id="defaultSwitcher" value="#{themeSwitcherBean.theme}">
<f:selectItems value="#{themeSwitcherBean.themes}" />
<p:ajax listener="#{themeSwitcherBean.saveTheme}" />
</p:themeSwitcher>
</h:form>
in your managedbean create the method who call saveTheme, that going to call a class to persist in database, and call the the class for the database when start to get the theme who had saved into the database:
#SessionScoped
#ManagedBean(name="themeSwitcherBean")
public class ThemeSwitcherBean implements Serializable{
private Map<String, String> themes;
private String theme;
private GuestPreferences gp;
private void setGp(GuestPreferences gp) {
this.gp = gp;
}
public Map<String, String> getThemes() {
return themes;
}
public String getTheme() {
return theme;
}
public void setTheme(String theme) {
this.theme = theme;
}
#PostConstruct
public void init() {
setGp(new GuestPreferences()); // persistent class
setTheme(gp.getTheme()); // theme from the database;
themes = new TreeMap<String, String>();
themes.put("Aristo", "aristo");
themes.put("Black-Tie", "black-tie");
themes.put("Blitzer", "blitzer");
themes.put("Bluesky", "bluesky");
themes.put("Bootstrap", "bootstrap");
themes.put("Casablanca", "casablanca");
themes.put("Cupertino", "cupertino");
themes.put("Dark-Hive", "dark-hive");
themes.put("Dot-Luv", "dot-luv");
themes.put("Eggplant", "eggplant");
themes.put("Excite-Bike", "excite-bike");
themes.put("Flick", "flick");
themes.put("Glass-X", "glass-x");
themes.put("Hot-Sneaks", "hot-sneaks");
themes.put("Humanity", "humanity");
themes.put("Le-Frog", "le-frog");
themes.put("Midnight", "midnight");
themes.put("Mint-Choc", "mint-choc");
themes.put("Overcast", "overcast");
themes.put("Pepper-Grinder", "pepper-grinder");
themes.put("Redmond", "redmond");
themes.put("Rocket", "rocket");
themes.put("Sam", "sam");
themes.put("Smoothness", "smoothness");
themes.put("South-Street", "south-street");
themes.put("Start", "start");
themes.put("Sunny", "sunny");
themes.put("Swanky-Purse", "swanky-purse");
themes.put("Trontastic", "trontastic");
themes.put("UI-Darkness", "ui-darkness");
themes.put("UI-Lightness", "ui-lightness");
themes.put("Vader", "vader");
}
public void saveTheme() {
gp.setTheme(theme); // theme to database
}
}
method theme from class GuestPreferences is going to persist to the database
#SessionScoped
public class GuestPreferences {
public String getTheme(){
//return the theme from the database
}
public void setTheme(String theme){
//send the theme to the database
}
}
the form to send and receive data from the database depends of you prefer:
* jdbc
* jta
* jpa
for example, jta, make a persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="NAME-WHAT-YOU-WANT" transaction-type="JTA">
<provider>CLASS-OF-YOUR-PROVIDER</provider>
<jta-data-source>YOUR-DATASOURCE</jta-data-source>
<class>PATH-OF.GuestPreferences</class>
<properties>
<property name="NAME-OF-PROPERTY-TO-FORM-A-JDBC-URL" value="VALUE-OF-PROPERTY"/>
<property name="NAME-OF-PROPERTY-TO-FORM-A-JDBC-URL" value="VALUE-OF-PROPERTY"/>
<property name="NAME-OF-PROPERTY-TO-FORM-A-JDBC-URL" value="VALUE-OF-PROPERTY"/>
</properties>
</persistence-unit>
</persistence>
in a resources class you can declare:
#SuppressWarnings("unused")
#Produces
#PersistenceContext
private EntityManager em;
then, you can use it in your GuestPreferences class:
#Inject
private EntityManager em;
em.getTransaction().begin();
Query query = em.createQuery("SELECT u FROM user_table u where u.iduser=:iduser");
query.setParameter("iduser", "THEME-USER-ID");
User resultUser = (User) query.getResultList();
em.getTransaction().commit();
if(User!=null){
return resultUser.getTheme();
}
code above assumes you have a table called user_table where a user has a iduser, name ..., and a theme column, and it assumes you have an object called User to manage users
One more way to do this: include stylesheet to your pages template:
<h:body>
<h:outputStylesheet library="primefaces-#{themesBean.theme}" name="theme.css" /> </h:body>
Where #{themesBean.theme} variable reffers to name of your theme.
P.S. tested in PF5
I think setting selected theme in session would help:
session.setAttribute
Edit web.xml through code:
http://illegalargumentexception.blogspot.co.at/2008/08/java-using-xmlbeans-to-edit-webxml.html
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>EDITME</param-value>
</context-param>
Or create method before loading your page to choose the theme from db. (cleaner solution)