How to use Spring boot 3 with JSF? - spring

I'm trying to create a JSF project managed by Spring boot 3.0. But it doesn't work no matter how I do it. I can't find any example on the web.
My dependencies:
implementation 'org.springframework.boot:spring-boot-starter-web:3.0.2'
implementation 'org.apache.tomcat.embed:tomcat-embed-jasper:10.1.5'
implementation 'org.glassfish:jakarta.faces:4.0.1'
testImplementation 'org.springframework.boot:spring-boot-starter-test:3.0.2'
My MainApplication class:
#SpringBootApplication
public class ManagementClientApplication implements ServletContextAware {
public static void main(String[] args) {
SpringApplication.run(ManagementClientApplication.class, args);
}
#Bean
public ServletRegistrationBean<FacesServlet> servletRegistrationBean() {
ServletRegistrationBean<FacesServlet> servletRegistrationBean = new ServletRegistrationBean<>(new FacesServlet(), "*.xhtml");
servletRegistrationBean.setLoadOnStartup(1);
return servletRegistrationBean;
}
#Override
public void setServletContext(ServletContext servletContext) {
servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", Boolean.TRUE.toString());
servletContext.setInitParameter("jakarta.faces.FACELETS_SKIP_COMMENTS", "true");
}
}
My config webapp/WEB-INF/faces-config.xml :
<?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/web-facesconfig_2_2.xsd"
version="2.2">
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
</faces-config>
A test XHTML file:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
</h:head>
<h:body>
<h:form>
<h:outputText id="greeting" value="Hello world !" />
</h:form>
</h:body>
</html>
Logs :
2023-02-02T17:21:10.844+01:00 INFO 6312 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2023-02-02T17:21:10.845+01:00 INFO 6312 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 738 ms
2023-02-02T17:21:11.133+01:00 ERROR 6312 --- [ main] jakarta.faces : Unable to obtain InjectionProvider from init time FacesContext. Does this container implement the Mojarra Injection SPI?
2023-02-02T17:21:11.149+01:00 ERROR 6312 --- [ main] jakarta.faces : L’application n’a pas été initialisée correctement au démarrage. Impossible de localiser la Fabrique : jakarta.faces.context.FacesContextFactory. Attempting to find backup.
2023-02-02T17:21:11.150+01:00 ERROR 6312 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Servlet.init() for servlet [facesServlet] threw exception
java.lang.IllegalStateException: Could not find backup for factory jakarta.faces.context.FacesContextFactory.
at jakarta.faces.FactoryFinderInstance.notNullFactory(FactoryFinderInstance.java:497) ~[jakarta.faces-4.0.1.jar:4.0.1]
at jakarta.faces.FactoryFinderInstance.getFactory(FactoryFinderInstance.java:190) ~[jakarta.faces-4.0.1.jar:4.0.1]
at jakarta.faces.FactoryFinder.getFactory(FactoryFinder.java:263) ~[jakarta.faces-4.0.1.jar:4.0.1]
at jakarta.faces.webapp.FacesServlet.acquireFacesContextFactory(FacesServlet.java:493) ~[jakarta.faces-4.0.1.jar:4.0.1]
Links I looked at:
How to properly configure Jakarta EE libraries in Maven pom.xml for Tomcat?
Spring Boot JSF Integration
Spring Boot JSF Integration
The project with Spring boot 2 and Javax that I tried to reproduce:
https://github.com/xtremebiker/jsf-spring-boot
I don't understand what I'm doing wrong. I can't find anything on the web. Any help would be welcome.
Thank you all

Related

What happens when i using #Bean and #Component annotations together?

I'm trying to configure my spring security application.
I want to create my own UserDetailsService.
For that i do something like this:
public class ApplicationUserService implements UserDetailsService {
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return this.someUser();
}
}
I got 2 ways to add this UserService to Spring Security
Add it to configuration class. Something like this:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
#Override
protected UserDetailsService userDetailsService() {
return applicationUserService;
}
}
Or add annotaion #Component, or #Service on my class.
Everything is working fine when i chose only 1 way, but i got an question: why when i trying to use both variants (add #Service and add #Bean to config) nothing is working?
I got no exceptions, error or something like this in console:
2021-09-11 17:26:16.755 INFO 15819 --- [ main] com.example.test.TestApplication : Starting TestApplication using Java 16.0.2 on aleksander-MS-7A71 with PID 15819 (/home/aleksander/programming/java/4fun/test/target/classes started by aleksander in /home/aleksander/programming/java/4fun/test)
2021-09-11 17:26:16.756 INFO 15819 --- [ main] com.example.test.TestApplication : No active profile set, falling back to default profiles: default
2021-09-11 17:26:17.402 INFO 15819 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-09-11 17:26:17.409 INFO 15819 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-09-11 17:26:17.409 INFO 15819 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.52]
2021-09-11 17:26:17.442 INFO 15819 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-09-11 17:26:17.442 INFO 15819 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 630 ms
2021-09-11 17:26:17.555 INFO 15819 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure any request with [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter#6981f8f3, org.springframework.security.web.context.SecurityContextPersistenceFilter#38bb9d7a, org.springframework.security.web.header.HeaderWriterFilter#62db3891, org.springframework.security.web.authentication.logout.LogoutFilter#48528634, org.springframework.security.web.authentication.www.BasicAuthenticationFilter#80bfdc6, org.springframework.security.web.savedrequest.RequestCacheAwareFilter#78d6447a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter#5e65afb6, org.springframework.security.web.authentication.AnonymousAuthenticationFilter#623dcf2a, org.springframework.security.web.session.SessionManagementFilter#2819c460, org.springframework.security.web.access.ExceptionTranslationFilter#6f49d153, org.springframework.security.web.access.intercept.FilterSecurityInterceptor#60bbacfc]
2021-09-11 17:26:17.676 INFO 15819 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2021-09-11 17:26:17.682 INFO 15819 --- [ main] com.example.test.TestApplication : Started TestApplication in 1.215 seconds (JVM running for 1.794)
The way you've described the question, the application will definitely throw an exception unless you've defined the bean preference.
First case:
Basically, UserDetailsService is an interface and you've provided the implementation of it by declaring the bean as
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
#Override
protected UserDetailsService userDetailsService() {
return new ApplicationUserService();
}
}
Second case: You want to check the behaviour by declaring another bean using #Service or #Component annotation as following
#Service
public class ApplicationUserService implements UserDetailsService {
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return new UserDetails();
}
}
If you try to use the above cases together, it won't work. The case is very simple you are providing two beans of type UserDetailsService to the spring container and hence it won't be able to identify which one it should use.
If you want to check the behaviour with both the cases you've to set the priority for beans, so in that case you can mark one of the bean with #Primary annotation.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Primary
#Bean
#Override
protected UserDetailsService userDetailsService() {
return new ApplicationUserService();
}
}

Not Found in ExternalContext as a Resource Error (Amazon Elastic Beanstalk / Spring Boot / JSF + Primefaces)

I created an app using Spring Boot, JSF + Primefaces. I deployed it to Amazon Elastic Beanstalk, and set the environment variables that project needed to use.
When I tried to access my website, I got this error message:
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Mar 04 07:21:33 UTC 2021
There was an unexpected error (type=Not Found, status=404).
/login.xhtml Not Found in ExternalContext as a Resource
Here is my Faces Config (as java class):
package com.jsf;
#SpringBootApplication
#Configuration
#ComponentScan("com.jsf")
public class HelloJsfApplication {
public static void main(String[] args) {
SpringApplication.run(HelloJsfApplication.class, args);
}
// JSF Configration Başlangıc
#Bean
public ServletRegistrationBean<FacesServlet> facesServletRegistraiton() {
ServletRegistrationBean<FacesServlet> registration = new ServletRegistrationBean<FacesServlet>(
new FacesServlet(), new String[] { "*.xhtml" });
registration.setName("Faces Servlet");
registration.setLoadOnStartup(1);
registration.addUrlMappings("*.xhtml");
return registration;
}
#Bean
public ServletContextInitializer servletContextInitializer() {
return servletContext -> {
servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", Boolean.TRUE.toString());
servletContext.setInitParameter("primefaces.THEME", "bootstrap");
// Primefaces client browser tarafında kontrol edilebilme örneğin textbox 10
// karakter olmalı vs..
servletContext.setInitParameter("primefaces.CLIENT_SIDE_VALIDATION", Boolean.TRUE.toString());
// Xhtml sayfalarında commentlerin parse edilmemesi.
servletContext.setInitParameter("javax.faces.FACELETS_SKIP_COMMENTS", Boolean.TRUE.toString());
// primefaces icon set için
servletContext.setInitParameter("primefaces.FONT_AWESOME", Boolean.TRUE.toString());
};
}
#Bean
public ServletListenerRegistrationBean<ConfigureListener> jsfConfigureListener() {
return new ServletListenerRegistrationBean<ConfigureListener>(new ConfigureListener());
}
// JSF Configration Sonu
}
my faces config file under webapp/WEB-INF folder:
<?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>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
</faces-config>
and as you see, all my xhtml files are under webapp folder:
my application.properties file (using java params):
server.servlet.context-path = ${CONTEXT_PATH}
server.port = ${PORT}
spring.datasource.url = ${SPRING_DATASOURCE_URL}
spring.datasource.username = ${SPRING_DATASOURCE_USERNAME}
spring.datasource.password = ${SPRING_DATASOURCE_PASSWORD}
spring.jpa.properties.hibernate.dialect = ${SPRING_JPA_DATABASE_PLATFORM}
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = ${SPRING_JPA_HIBERNATE_DDL_AUTO}
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=${SPRING_JPA_HIBERNATE_LOB_CREATION}
spring.datasource.driver-class-name=${SPRING_DATASOURCE_DRIVERCLASSNAME}
and here are java parameters that I defined on Amazon (I will not post db params for security reasons):
PORT=5000
CONTEXT_PATH=/
SPRING_DATASOURCE_DRIVERCLASSNAME=org.postgresql.Driver
...
and so on.
Really I run out of solutions. With same packaged jar, I deployed to Heroku with same environment parameters, and it works flawlessly.
Where I am doing wrong with Amazon Elastic Beanstalk?
Kind regards.
I found the problem.
Maven, does not add *.xhtml files inside "jar" package.
Here is the ss of decompiled version of jar packaging (with jd-gui)
..and here is the ss of war packaging:
so if you are think that you did everything correct during development and managing after, check the packaging type.

error with spring template parsing

I started from new Spring Boot project included Web, Devtools, JPA and Mustache modules.
I have simple controller:
package com.example.elephant;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.HashMap;
import java.util.Map;
#Controller
public class IndexController {
#GetMapping("/")
public ModelAndView index() {
Map<String, String> model = new HashMap<>();
model.put("name", "Spring");
System.out.println("11111111111111111111");
return new ModelAndView("index",model);
}
}
and simple template /resources/templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{name}}
</body>
</html>
application class:
package com.example.elephant;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class ElephantApplication {
public static void main(String[] args) {
SpringApplication.run(ElephantApplication.class, args);
}
}
Application log:
2018-04-24 15:09:11.333 INFO 7402 --- [ restartedMain] c.example.elephant.ElephantApplication : Started ElephantApplication in 5.906 seconds (JVM running for 6.477)
2018-04-24 15:09:29.231 INFO 7402 --- [nio-8036-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-04-24 15:09:29.232 INFO 7402 --- [nio-8036-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2018-04-24 15:09:29.252 INFO 7402 --- [nio-8036-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 19 ms
11111111111111111111
All ok, but I have 404 error. It seems I have a problem with template parsing but I can't understand why.
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Tue Apr 24 15:09:29 MSK 2018
There was an unexpected error (type=Not Found, status=404).
No message available
You have to rename your template file to:
index.mustache
The file ending has changed with Spring Boot 2 from html to mustache:
https://github.com/spring-projects/spring-boot/issues/8997

GlassFish Server status 404 No mapping found for HTTP request with URI in DispatcherServlet

I'm trying to integrate JSF 2 with Spring and I was following this example and making some modifications to access a DB and execute a Stored Procedure.
But when I run the project I'm getting a Status 404 - Not found from the GlassFish Server. In the console log I'm getting the message:
Warning: No mapping found for HTTP request with URI [/] in DispatcherServlet with name 'dispatcher'
Here is my resulting code:
Folder Structure
Initializer.java
public class Initializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
ctx.setServletContext(servletContext);
servletContext.addListener(new ContextLoaderListener(ctx));
servletContext.addListener(new RequestContextListener());
Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
dynamic.addMapping("/");
dynamic.setLoadOnStartup(1);
}
}
AppConfig.java
#Configuration
#ComponentScan("source")
class AppConfig {
#Bean
public Service service() {
DriverManagerDataSource ds = new DriverManagerDataSource("jdbc:mysql://localhost:3306/test?zeroDateTimeBehavior=convertToNull", "root", "rootPass");
ds.setDriverClassName("com.mysql.jdbc.Driver");
return new ServiceImpl(ds);
}
}
ProcBean.java
#ManagedBean(name = "procBean", eager = true)
#RequestScoped
#Component
#RequestMapping("/")
public class ProcBean {
private int input;
private int output;
#Autowired public Service procService;
// Empty constructor, getters/setters
public String callStoredProcedure() {
this.output = procService.callStoredProcedure(input);
return "output";
}
}
ServiceImpl.java
public class ServiceImpl implements Service {
private DataSource dataSource;
private StoredProcedurePrueba prueba;
public ServiceImpl(DataSource dataSource) {
this.dataSource = dataSource;
}
// get/set dataSource
#Override
public int callStoredProcedure(int input) {
this.prueba = new StoredProcedurePrueba(dataSource);
return this.prueba.execute(input);
}
private class StoredProcedurePrueba extends StoredProcedure {
// Implementation tested separately and working correctly
}
}
Configuration
faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
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">
<application>
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
</faces-config>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1"
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-app_3_1.xsd">
<display-name>JSF 2 + Spring 4 Integration Example</display-name>
<servlet>
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>FacesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
Web pages
<!-- input.xhtml -->
<h:body>
<h3>JSF 2 + Spring 4 Integration Example</h3>
<h:form id="studentForm">
<h:outputLabel value="Enter Student id:" />
<h:inputText value="#{procBean.input}" /> <br />
<h:commandButton value="Submit" action="#{procBean.callStoredProcedure()}"/>
</h:form>
</h:body>
<!-- output.xhtml -->
<h:body>
<h3>JSF 2 + Spring 4 Integration Example</h3>
<p>#{procBean.output}</p>
</h:body>
I was trying some other solutions but none of them works for me. Any idea? What am I missing?
Thanks in advance for your answers.
Not using Spring but I would think you need a welcome-file in web.xml like
<welcome-file-list>
<welcome-file>input.xhtml</welcome-file>
</welcome-file-list>

Spring context:component-scan not working with annotated beans

I'm trying to run a simple Spring + Hibernate tutorial => Maven Spring Hibernate annotation example
My beans definition file BeanLocations.xml is like this :
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- Database Configuration -->
<import resource="../database/Datasource.xml"/>
<import resource="../database/Hibernate.xml" />
<context:component-scan base-package="com.sample.springhibernate"/>
</beans>
My main method:
public static void main( String[] args )
{
ApplicationContext appContext = new ClassPathXmlApplicationContext("classpath*:BeanLocations.xml");
StockBo stockBo = (StockBo)appContext.getBean("stockBo");
}
I have a defined service with an interface:
public interface StockBo {
public void save(Stock stock);
public void update(Stock stock);
public void delete(Stock stock);
public Stock findByStockCode(String stockCode);
}
And his implementation:
#Service("stockBo")
public class StockBoImpl implements StockBo {
#Autowired
StockDao stockDao;
public void setStockDao(StockDao stockDao){
this.stockDao = stockDao;
}
#Override
public void save(Stock stock) {
stockDao.save(stock);
}
........
There is any problem with this because spring throws a Exception when StockBo)appContext.getBean("stockBo") :
30-oct-2014 15:31:49 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext#64dc11: display name [org.springframework.context.support.ClassPathXmlApplicationContext#64dc11]; startup date [Thu Oct 30 15:31:49 CET 2014]; root of context hierarchy
30-oct-2014 15:31:49 org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
INFO: Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext#64dc11]: org.springframework.beans.factory.support.DefaultListableBeanFactory#a3d4cf
30-oct-2014 15:31:49 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#a3d4cf: defining beans []; root of factory hierarchy
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'stockBo' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:387)
Spring not foud my annotated service StockBoo (with #Service("stockBo") )....
What is the problem? How can I ensure that Spring recognize my service with component scan?
FYI: StockBo is in com.sample.springhibernate.bo and StockBoImpl in com.sample.springhibernate.bo.impl
If you turn your log level to DEBUG, you'll more than likely find a line like
DEBUG o.s.b.f.xml.XmlBeanDefinitionReader - Loaded 0 bean definitions from location pattern [classpath*:BeanLocations.xml]
That is, your ClassPathXmlApplicationContext did not find any resources that match classpath*:BeanLocations.xml and therefore didn't load any context.
You'll need to provide a resource location String value that properly identifies and locates the context configuration file.

Resources