This example creates jsf composite component that handles login.
When composite component is included in the page, actually whole subtree of components is included with parent top level component that is actual representation of composite component. This is just a simple showcase, but when developing more complicated composite components, sometimes it is handy to implement behavior using java code instead of only using xhtml markup. So, this example will create some sort of backing class for the composite component.
First, here is an example of using page that uses login component:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:g="http://java.sun.com/jsf/composite/components"> <h:body> <p>Login to access secure pages:</p> <h:form id="loginComponent"> <g:login login="#{authBackingBean.login}" success="/admins/admins?faces-redirect=true"/> </h:form> </h:body> </html>
And the actual login is performed by #{authBackingBean.login} method that is called by our composite component when user clicks login button. Only requirement for login method is that it must return boolean value and accept two String parameters (that will be username and password). Here is an example of backing bean:
@ManagedBean @RequestScoped public class AuthBackingBean { private static Logger log = Logger.getLogger(AuthBackingBean.class.getName()); public boolean login(String username, String password) { FacesContext context = FacesContext.getCurrentInstance(); HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getRequest(); try { request.login(username, password); } catch (ServletException e) { context.addMessage(null, new FacesMessage( FacesMessage.SEVERITY_WARN, "Login failed!", null)); return false; } Principal principal = request.getUserPrincipal(); log.info("Authenticated user: " + principal.getName()); return true; } }
Composite component is then responsible for calling login method with parameters that are entered by user and submited as username and password.
Below is an example of composite login component. It consists of login.xhtml facelet file and LoginComponent class that extends UINamingContainer component.
login.xhtml markup file should be placed in resource library folder. Resource library is folder named resources in the top-level web application root and is accessible to the classpath.
In my example, I have resources/components folder that contains login.xhtml facelet file.
The name of the resource library is what comes after http://java.sun.com/jsf/composite and is actually the name of subdirectory that resides in resources folder. In code snipet above, i have http://java.sun.com/jsf/composite/components namespace since my component is in components subdirectory.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:composite="http://java.sun.com/jsf/composite"> <composite:interface componentType="loginComponent"> <composite:attribute name="login" required="true" method-signature="boolean f(java.lang.String, java.lang.String)"/> <composite:attribute name="success" required="true"/> <composite:attribute name="failure" required="false"/> </composite:interface> <composite:implementation> <h:panelGrid columns="2"> <h:outputLabel for="#{cc.clientId}:username" value="Username:" /> <h:inputText id="username" binding="#{cc.username}" /> <h:outputLabel for="#{cc.clientId}:password" value="Password:" /> <h:inputSecret id="password" binding="#{cc.password}" /> <h:commandButton id="loginButton" value="Login" action="#{cc.action}" actionListener="#{cc.actionListener}" /> </h:panelGrid> </composite:implementation> </html>
I will not go into detail about interface and implementation sections, there is plenty of articles about composite components.
Here is important to note that componentType on interface tag is interpreted as component type of a component already registered with JSF and when JSF runtime encounters a composite component tag of that type it will create instance of that component that will serve as the composite component root (top level component).
Interface section declares method attribute login that has two String parameters and will be called when user clicks login button and will perform actual login process. Login method is called by backing UIComponent class for showcase purpose to show how method expression can be called manually from java code . If there were no custom backing UIComponent attached to this composite component, than method expresion could be attached directly to action attribute of login button.
In case of successful login, success attribute is used as outcome where user will be redirected.
Interesting thing is also #{cc.action} and #{cc.actionListener} action methods that point directly to methods on actual UIComponent that is top-level component. JSF assumes that top-level component for composite component is javax.faces.component.NamingContainer component.
The easiest way is to extend javax.faces.component.UINamingContainer. Here is an example of backing component for composite component:
@FacesComponent(value="loginComponent") public class LoginComponent extends UINamingContainer { private UIInput username; private UIInput password; private String action; public LoginComponent() { super(); } public void actionListener(ActionEvent ae) { FacesContext context = FacesContext.getCurrentInstance(); ELContext elContext = context.getELContext(); Object params[] = new Object[2]; params[0] = username.getValue(); params[1] = password.getValue(); MethodExpression me = (MethodExpression)this.getAttributes().get("login"); boolean loginSuccess = (Boolean)me.invoke(elContext, params); if(loginSuccess) { action = (String)getAttributes().get("success"); } else { action = (String)getAttributes().get("failure"); } } public String action() { return action; } public UIInput getUsername() { return username; } public void setUsername(UIInput username) { this.username = username; } public UIInput getPassword() { return password; } public void setPassword(UIInput password) { this.password = password; } }
@FacesComponent annotation registers this UIComponent with JSF runtime. Notice that annotation value loginComponent matches the value of componentType in login.xhtml facelet file. When user clicks login button, ActionListener method is called. Login method expression is obtained from attributes map and submited username and password values are obtained from binded UIInput components. This values are then used as parameters to invoke login method.
Depending on method invocation result, action variable is then set with success or failure attribute value and is used as outcome for login button so that user is redirected to appropriate view.
Hi,
ReplyDeleteWe are following your example, however we are not quite sure where you get the 'cc' part from and what that points to eg.binding="#{cc.username}"
Any help would be appreciated!
cheers
Hi,
Delete'cc' is a reserved word in JSF for composite component and in my case that is LoginComponent. So, cc.username binds to username UIInput variable in LoginComponent class.
Hi, Gordan,
ReplyDeleteThanks for Your work! It's helpful.
Instead of 'cc' :)
At JBoss 7.1.0.Final I've got an exception:
javax.el.PropertyNotFoundException: /resources/components/login.xhtml @18,57 binding="#{cc.username}": Target Unreachable, identifier 'cc' resolved to null
And I'm absolutely sure that my backing Auth bean exists and LoginComponent is exists in classpath, because I inserted a component at my existing working login page.
What can I do to avoid an exception?
Cheers!
Alexander.
Did you solve this? I've the same problem.
DeleteUsing Tomcat 7.0.26 + PrimeFaces 3.3.1
I had the same problem but i was making a mistake, because i was overriding saveState but without saving and restoring super.saveState so all the attributes was lost !
DeleteHi,
ReplyDeleteI tried the example in both JSF 2.0/Weblogic and Mojarra JSF 2.1.11/Tomcat. But both cc.clientId and cc:password cannot be evaluated. Did you encounter this problem before? Have your code been tested in the environments listed above yet?
Thanks.
Hi
DeleteI want to try the code; Have you tested the code with jsf 2.0 + mojarra 2.0.3 + servlet api 3.0 which are quite compatible?
p.s. as I can remember, the composite *.xhtml should be located in (lets say in eclipse case) WebContent/resources/components
nice article .
ReplyDeleteKeep sharing !
looking forward to it.
full stack developer course
Good Post! it was so good to read and useful to improve my knowledge as an updated one, keep blogging. After seeing your article I want to say that also a well-written article with some very good information which is very useful for the readers....thanks for sharing it and do share more posts like this.
ReplyDeleteLooking for the best ppc course in Bangalore? Learn PPC from Ranjan Jena, 10+ Years Expert Google Ads Trainer. 1000+ Students Trained @ eMarket Education, Koramangala, Bangalore.
Best Online Digital Marketing Courses in Bangalore, India
Best Digital Marketing Institute in Bangalore
This blog is definitely interesting additionally informative. I have picked up many useful tips out of this source. I ad love to come back again soon. Thanks a lot! for More Details Click Here: Air Hostess course
ReplyDeleteVery interesting blog. Many blogs I see these days do not really provide anything that attracts others, but believe me the way you interact is literally awesome. You can also check my articles as well.
ReplyDeletebest overseas consultants in bangalore
ms in mechanical engineering in germany
Masters in Mechanical Engineering in Germany
free education in germany
mba in germany
ms in germany for indian students
study ms in germany
study in germany consultants
Nice article.keep posting
ReplyDeleteAzure devops training in hyderabad
https://bayanlarsitesi.com/
ReplyDeleteEskişehir
Erzincan
Ardahan
Erzurum
DFO
tekirdağ
ReplyDeletetokat
elazığ
adıyaman
çankırı
BQX
whatsapp görüntülü show
ReplyDeleteücretli.show
M7Z
Bolu Lojistik
ReplyDeleteMardin Lojistik
Kocaeli Lojistik
Diyarbakır Lojistik
İstanbul Lojistik
YNWQUL
7FF19
ReplyDeleteDüzce Şehir İçi Nakliyat
Bayburt Şehirler Arası Nakliyat
Bitrue Güvenilir mi
Adıyaman Parça Eşya Taşıma
Antep Evden Eve Nakliyat
Vindax Güvenilir mi
Silivri Evden Eve Nakliyat
Adana Şehirler Arası Nakliyat
Çanakkale Evden Eve Nakliyat
A1677
ReplyDeletepeptides for sale
order primobolan
primobolan
clenbuterol for sale
masteron for sale
testosterone enanthate
winstrol stanozolol
sustanon for sale
oxandrolone anavar for sale
FA8D6
ReplyDeleteÇerkezköy Çatı Ustası
Bilecik Evden Eve Nakliyat
turinabol
buy sarms
Bolu Evden Eve Nakliyat
buy halotestin
İstanbul Evden Eve Nakliyat
Iğdır Evden Eve Nakliyat
Kalıcı Makyaj
08ACF
ReplyDeletemobil sohbet
konya random görüntülü sohbet
görüntülü canlı sohbet
erzurum görüntülü sohbet sitesi
Ardahan Bedava Sohbet Chat Odaları
izmir görüntülü sohbet siteleri
muş ücretsiz sohbet odaları
tokat sesli sohbet sitesi
gümüşhane rastgele görüntülü sohbet ücretsiz
شركة تنظيف شقق بالجبيل H5P6drS3qW
ReplyDeleteشركة مكافحة حشرات بخميس مشيط o2ioG3Y4wM
ReplyDelete