How to validate availability of username in database? - ajax

How can I validate the entered username in an input text field if it is available according to the database? I am using JSF2.

Just implement a Validator yourself.
#ManagedBean
#RequestScoped
public class UserNameAvailableValidator implements Validator {
#EJB
private UserService userService;
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
String userName = (String) value;
if (!userService.isUsernameAvailable(userName)) {
throw new ValidatorException(new FacesMessage("Username not avaliable"));
}
}
}
(please note that it's a #ManagedBean instead of #FacesValidator because of the need to inject an #EJB; if you're not using EJBs, you can make it a #FacesValidator instead)
Use it as follows:
<h:inputText id="username" value="#{register.user.name}" required="true">
<f:validator binding="#{userNameAvailableValidator}" />
<f:ajax event="blur" render="username_message" />
</h:inputText>
<h:message id="username_message" for="username" />

Related

#ViewScoped bean behaves like #SessionScoped or #ApplicationScoped

I have a Spring Boot application using JSF/CDI. Backing beans are annotated with #Named #ViewScoped, but while browsing between other pages values still stay on textboxes. Values should've been cleared. In other words, the backing beans unexpectedly behave like #SessionScoped or #ApplicationScoped.
My input
<p:inputText value="#{parameterBean.spreadValue}" label=" "
styleClass="inputText" id="spreadValue">
<p:ajax event="change" />
<p:ajax event="valueChange" />
</p:inputText>
My bean
#Named("parameterBean")
#ViewScoped
public class parameterBean implements Serializable {
// ...
}
This is JSF configuration
#Configuration
public class JSFConfig {
#Bean
ServletRegistrationBean<FacesServlet> jsfServletRegistration(ServletContext servletContext) {
servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", Boolean.TRUE.toString());
// FacesServlet registration
ServletRegistrationBean<FacesServlet> srb = new ServletRegistrationBean<>();
srb.setServlet(new FacesServlet());
srb.setUrlMappings(Arrays.asList("*.xhtml"));
srb.setLoadOnStartup(1);
return srb;
}
}

How to pass Injected/Autowired object from Spring to ManagedBean?

I am working on a project with Spring and EJB/Primefaces and I want to pass values from the spring context to a managed bean. I will demonstrate with a sample code to clarify further.
Let's say we have the following domain class (I keep it simple for better readability):
public class Store {
#JsonProperty("store_name")
private String storeName;
//constructors, getters and setters...
}
The reason of #JsonProperty is because I am getting this value from an other application that POSTs a Json to the following Controller:
#Controller
#RequestMapping("/store")
public class StoreController {
#Autowired
private Store store;
#RequestMapping(method = RequestMethod.POST)
public String getStoreResponse(#RequestBody String store) throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
LOGGER.info("Store Before Post: " + store.getName());
store = mapper.readValue(request, Store.class);
LOGGER.info("Store After Post: " + store.getName());
return "store";
}
}
I have configured the store bean at a BeanConfig class:
#Configuration
public class BeanConfig {
#Bean(name = "store")
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Store store() {
Store store = new Store();
store.setName("Test Store Name");
return store;
}
}
This is my managed bean:
#ManagedBean
#SessionScoped
public class StoreView extends SpringBeanAutowiringSupport {
private static final Logger LOGGER = LoggerFactory.getLogger(Store.class);
//#ManagedProperty("#{store}")
#Autowired
private Store store;
public void test() {
LOGGER.info("TEST " + store.getName());
}
//getters and setters
}
finally my xhtml:
<h:panelGrid columns="3">
<p:outputLabel for="j_store" value="#{messages['storeview.name']}" />
<p:inputText id="j_store" value="#{storeView.store.name}" />
<p:message for="j_store" />
<h:panelGroup />
<p:commandButton value="#{messages['storeview.test']}" action="#{storeView.test}" update="#form" ajax="false" />
</h:panelGrid>
When I am posting sample data using postman, the first time, the logger outputs:
10:35:57,433 INFO [com.store.test.controllers.StoreController] (default task-2) Store Before Post: Test Store Name
10:35:57,488 INFO [com.store.test.controllers.StoreController] (default task-2) Store After Post: posted store name
and if I continue calling the controller I keep getting the "posted store name", so it has kept the value.
But when I am going to the store.xhtml and hit the test button to submit the form, it still has the value set in the bean configuration file ("Test Store Name") and from that point on it keeps the value that I submit in the inputText.
I suspect it has to do with Spring and Faces context, I do not know if what I want to do is possible. If it is, please point out what should I change to make it work, otherwise, please provide me with an alternative solution.
Thanks in advance.
You are mixing #Autowired and #ManagedBean annotations.
#Autowired is managed by Spring while #ManagedBean is managed by JSF.
That means that probably you will have 2 instances of Store, the one modified by controller is not the same instance used by the managed bean.
You should annotate as #ManagedProperty("#{store}") your store attribute in managed bean and define getter and setter.
To get it to work you also must define spring Expression Language resolver in faces-config.xml
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
Since jsf session is different from mvc session, you also have to use singleton scope in the definition of Store object.
#Scope(value = "singleton"........

Using JSF2 #ManagedProperty in Spring managed backing bean

I have a JSF backing bean that is Spring managed but I would like to be able to make use of the #ManagedProperty from JSF. The following does not work:
#Component
#Scope(Scopes.REQUEST)
public class MyRequestBean {
#ManagedProperty(value="#{param.bcIndex}")
private int bcIndex;
public int getBcIndex() {
return bcIndex;
}
public void setBcIndex(int bcIndex) {
this.bcIndex = bcIndex;
}
}
Suggestions?
Actually it is quite simple. I know of three ways to do your injection:
Use Spring's #Value annotation together with implicit El #{param} object:
#Value("#{param.bcIndex}")
private int bcIndex;
Make use of ExternalContext#getRequestParameterMap in a #PostConstruct / preRenderView listener:
//#PostConstruct
public void init() {
bcIndex = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("bcIndex");
}
Make a binding in your view utilizing <f:viewParam>:
<f:metadata>
<f:viewParam name="index" value="#{myRequestBean.bcIndex}" />
</f:metadata>

JSF2/Primefaces dataTable sort not working with ViewScoped bean

I wanted to add sorting to a PrimeFaces 3.3 dataTable and created the following ViewScoped bean which stores the list so it is not fetched all the time from the EJB:
#Named
#ViewScoped
public class CustomerList implements Serializable {
private static final long serialVersionUID = 6168621124401208753L;
#EJB
CustomerEJB customerBean;
List<Customer> allCustomers = null;
public void loadCustomerList() {
allCustomers = customerBean.findAll();
}
public List<Customer> getList() {
if (allCustomers == null) {
loadCustomerList();
}
return allCustomers;
}
}
and this is the view using the bean:
<ui:composition template="/WEB-INF/templates/template.xhtml">
<ui:define name="content">
<h:form id="customerList">
<p:dataTable id="customer" var="customer"
value="#{customerList.list}" sortBy="#{customer.id}"
paginator="true" rows="10" paginatorAlwaysVisible="false"
paginatorPosition="top">
<p:column sortBy="#{customer.id}">
<f:facet name="header">
<h:outputText value="#{msg.customerIdLabel}" />
</f:facet>
<h:outputText value="#{customer.id}" />
</p:column>
<p:column sortBy="#{customer.lastName}">
<f:facet name="header">
<h:outputText value="#{msg.customerLastNameLabel}" />
</f:facet>
<h:outputText value="#{customer.lastName}" />
</p:column>
The issue is that i can click the column headers for sorting, but the table remains unsorted, even the initial sorting is not working. When u set a breakpoint in the getList() method i can see that the list is fetched several times from the EJB during when a request is processed.
Shouldn't the bean be stored as long as the view is active by ViewScope?
First of all, not related directly to your problem but:
You should never place your business methods into component getters (even with that null check I think that this is a bad practice). Use the #PostConstruct annotation instead:
#PostConstruct
public void loadCustomerList() {
allCustomers = customerBean.findAll();
}
public List<Customer> getList() {
return allCustomers;
}
loadCustomerList will be called every time when your ViewScoped bean is constructed.
Also, check your imports for scope annotations:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
Finally you class should look like:
#ViewScoped
#ManagedBean
public class CustomerList implements Serializable {
...
}
#ViewScoped is not supported in CDI so If you need to use #ViewScoped in CDI you should
use seam-faces or MyFaces CODI module. just add one of them to your classpath and #ViewScoped will work in CDI. MyFaces CODI has an even more solid support of #ViewScoped
use MyFaces CODI's #ViewAccessScoped, it is an extension written on top of CDI by Apache, just download it and use the #ViewAccessScoped annotation instead of #ViewScoped.
Use CDI #ConversationScoped and make it long running. see here for more info.
Unfortunately the seam3 solution has a memory leak problem so don't use seam3 for this special problem better solutions is CODIs #ViewAccessScoped.
See : Memory leak with ViewScoped bean?
you need to use this Annotation Bean combination:
for #ManagedBean u need to use #ViewScoped
for #Named (CDI) u need to use #ConversationScoped

How to enable JSR-303 bean validation in Facelets?

I'm using spring CDI and a customized "View" scope. (See this about how it works.)
The view bean is annotated with JSR-303 validation rules as following:
#Scope("view")
public class MyBean implements Serializable {
String message;
#NotNull
#Size(min = 10)
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void action1() {
...
}
}
And the user form:
...
<h:form id="form1">
<h:inputText name="message" value="${myBean.message}" />
<p:commandButton value="Update" actionListener="${myBean.action1}" />
</h:form>
However, the validation doesn't work. Am I missing something in faces-config.xml? I guess there should be some proxy classes involved in, which maybe generated by AspectJ weaver or so. Right?
JSR 303 validation for JSF is auto enabled if you add implementation jar to classpath.

Resources