📜 ⬆️ ⬇️

JSF 2 + Maven + Jetty. CDI, form and AJAX

This time we will have Java code. We will write the form and logic of processing the entered data. The post is NOT for those who know what JSF 2 and / or JSF 1.2 is, and faces-config.xml is not just a file in the project. Look, I warned ...

CDI


Since JSF 2.3.0, the standard @ManagedBean annotation @ManagedBean been deprecated. Those. in order to access your Java code from the form, we will need to add a CDI (Context and Dependency Injection) - Weld to the project.

Add to pom.xml file:

  <dependencies> ... <dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet</artifactId> <version>2.4.3.Final</version> </dependency> </dependencies> 

Create a file /src/main/webapp/WEB-INF/beans.xml :
')
 <?xml version="1.0" encoding="UTF-8"?> <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"> </beans> 

Bad advice
In the comments to the last post noticed:

Are there any special specifics in listener registration?

OK! Add to the /src/main/webapp/WEB-INF/web.xml file:
 <web-app ... <listener> <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> </listener> ... </web-app> 

Run: mvn jetty:run

We read the traceback why it does not work.

Create the file /src/main/webapp/WEB-INF/jetty-env.xml :

 <?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd"> <Configure id="webAppCtx" class="org.eclipse.jetty.webapp.WebAppContext"> <Call name="prependServerClass"> <Arg>-org.eclipse.jetty.server.handler.ContextHandler</Arg> </Call> <Call name="prependServerClass"> <Arg>-org.eclipse.jetty.servlet.FilterHolder</Arg> </Call> <Call name="prependServerClass"> <Arg>-org.eclipse.jetty.servlet.ServletContextHandler</Arg> </Call> <Call name="prependServerClass"> <Arg>-org.eclipse.jetty.servlet.ServletHolder</Arg> </Call> <New id="BeanManager" class="org.eclipse.jetty.plus.jndi.Resource"> <Arg> <Ref id="webAppCtx"/> </Arg> <Arg>BeanManager</Arg> <Arg> <New class="javax.naming.Reference"> <Arg>javax.enterprise.inject.spi.BeanManager</Arg> <Arg>org.jboss.weld.resources.ManagerObjectFactory</Arg> <Arg/> </New> </Arg> </New> </Configure> 

Add to the /src/main/webapp/WEB-INF/web.xml file:

 <web-app ... <resource-env-ref> <resource-env-ref-name>BeanManager</resource-env-ref-name> <resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type> </resource-env-ref> ... </web-app> 

Now @ManagedBean will work @Named . Considering that CDI is a good thing, but since JSF 2.3.0 is critical, it is worth understanding that CDI in JSF is used for its intended purpose and has no direct relation to JSF.
We will not return to CDI anymore!

Classes FormData and FormCtrl


Now let's write some code. We will need 2 classes - in the 1st we will transfer data, in the 2nd there will be a function of processing this data.

Retreat
From the point of view of implementation, it is not necessary to single out the logic of the form into 2 separate classes, but this is “correct” both from the point of view of testing and from the point of view of architecture.

The data /src/main/java/ru/habr/FormData.java :

 package ru.habr; import javax.enterprise.context.RequestScoped; import javax.inject.Named; @Named @RequestScoped public class FormData { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } 

Handler /src/main/java/ru/habr/FormCtrl.java :

 package ru.habr; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; @Named @RequestScoped public class FormCtrl { @Inject FormData formData; public String doAction() { //     ... System.out.println(formData.getUsername()); System.out.println(formData.getPassword()); return null; } } 

If everything is clear with FormData , then it is worth looking more closely at FormCtrl :

  1. Thanks to @Inject , these forms will be available in the class handler in the formData field.
  2. I recommend sticking to the thesis “the handler method should return a string”, although this is not necessary. The string is further used in navigation, but more on that later.

The form


Everything is simple! Add to the /src/main/webapp/index.xhtml file:

 <h:body> ... <h:form id="habrForm"> <h:inputText value="#{formData.username}"/><br/> <h:inputSecret value="#{formData.password}"/><br/> <h:commandButton action="#{formCtrl.doAction}" value="Send"> </h:commandButton> </h:form> </h:body> 

Run: mvn jetty:run
Checking: http://127.0.0.1:8080/

AJAX


It's 2017 in the yard, and the forms are still without AJAX ?! In the /src/main/webapp/index.xhtml file /src/main/webapp/index.xhtml make a couple of edits:

 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:f="http://xmlns.jcp.org/jsf/core"> ... <h:body> ... <h:inputText value="#{formData.username}"/><br/> <h:inputSecret value="#{formData.password}"/><br/> <h:commandButton action="#{formCtrl.doAction}" value="Send"> <f:ajax execute="@form" render="@form"/> </h:commandButton> </h:body> </html> 

What changed:

  1. Added definition of tag library xmlns:f="http://xmlns.jcp.org/jsf/core" . Without this, you can implement AJAX, but it will have to handle with pens, which is long and ungrateful.
  2. Inside h:commandButton , <f:ajax execute="@form" render="@form"/> . In execute , we indicate what needs to be sent to the server (all form / all fields of the form), in render , what needs to be updated from the server after AJAX has been completed.

About f:ajax you can write separate. Now it is enough to know just that with its help you can send / update not only the current form on the page, but any element of the page.

Afterword


The project is still very modest in its capabilities, but I will continue!

Source: https://habr.com/ru/post/330146/


All Articles