i can't reach my method with primefaces ajax - spring

i have an issue with my project, i'm using spring , jsf and primefaces, the problem is when i wish to call a method with ajax request, i can't and i have no error message to help me found the problem this is my first configuration with spring and jsf with annotations.
help me please .
my configuration:
#Configuration
#ComponentScan
#EnableTransactionManagement
public class AppConfig {
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306 /carouzetDb?useUnicode=true&useJDBCCompliantTimezoneShift=true& useLegacyDatetimeCode=false&serverTimezone=UTC");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
private Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty(
"hibernate.hbm2ddl.auto", "create");
hibernateProperties.setProperty(
"hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
return hibernateProperties;
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan("com.crouzet.carouzetroject.entities");
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public PlatformTransactionManager hibernateTransactionManager() {
HibernateTransactionManager transactionManager
= new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
}
public class MvcContentInitializer 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));
}
}
jsf 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>
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.FileUploadRenderer</renderer-type>
<renderer-class>com.crouzet.carouzetroject.FileUploadRenderer</renderer-class>
</renderer>
</render-kit>
</faces-config>
and here is the example where i call my method:
#ManagedBean(name = "helloBean")
#ViewScoped
#Component
public class HelloBean {
List<Salarie> salaries;
List<Categorie> categories;
List<Poste> postes;
Production production;
Categorie selectedCat;
#Autowired
private CategorieDAO categorieDAO;
#Autowired
private SalarieDAO salarieDAO;
#PostConstruct
public void init(){
categories=categorieDAO.allCategories();
System.out.println("==========>>>FROM INIT"+categories.size());
}
public void actualiser(){
categories=categorieDAO.allCategories();
}
public void listeDesSalaries(){
System.out.println("========AAAAAAAAAAAAAA========>>>>");
if(selectedCat!=null)
salaries=salarieDAO.salariesParCategorie(selectedCat);
}
public List<Salarie> getSalaries() {
return salaries;
}
public void setSalaries(List<Salarie> salaries) {
this.salaries = salaries;
}
public List<Categorie> getCategories() {
return categories;
}
public void setCategories(List<Categorie> categories) {
this.categories = categories;
}
public List<Poste> getPostes() {
return postes;
}
public void setPostes(List<Poste> postes) {
this.postes = postes;
}
public Production getProduction() {
return production;
}
public void setProduction(Production production) {
this.production = production;
}
public Categorie getSelectedCat() {
return selectedCat;
}
public void setSelectedCat(Categorie selectedCat) {
this.selectedCat = selectedCat;
}
}
and here is my page
<h:form>
<p:commandButton action="#{helloBean.actualiser()}" value="Actualiser" update="mesListes"/>
<p:panelGrid id="mesListes" columns="2">
<p:outputLabel value="Ligne de fabrication"/>
<p:selectOneMenu id="categori" value="#{helloBean.selectedCat}">
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems value="#{helloBean.categories}" var="cat" itemLabel="#{cat.nom}" itemValue="#{cat}" />
<p:ajax listener="#{helloBean.listeDesSalaries()}" />
</p:selectOneMenu>
</p:panelGrid>
</h:form>

Related

Spring MVC Servlet when deploying war to tomcat

I have already deploy war spring MVC to tomcat9. it's already running but in spring I create getmapping("/tesget") but when I created the servlet, result getmapping is wrong.
controller:
#GetMapping("tesget")
#ResponseStatus(HttpStatus.OK)
public List getTes2() throws Exception {
return userService.getTes2();
}
servlet:
public class Servlet extends HttpServlet {
public void init() throws ServletException
{
// Do required initialization
}
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>Servlet Testing</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("Welcome to the Servlet Testing Center");
out.println("</BODY>");
out.println("</HTML>");
}
public void destroy()
{
// do nothing.
}
}
web.xml:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<servlet>
<servlet-name>Servlet</servlet-name>
<servlet-class>com.project.maven.config.Servlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Before I created servlet and war, I running usually and when I go to localhost:8080/SpringNew/tesget, the result is true, list JSON from database, but when I create servlet, the url localhost:8080/SpringNew/tesget is wrong. the result is:
Welcome to the Servlet Testing Center
how to fix this problem? Thanks.
Bobby
AppInitializer.java
public class AppInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
ctx.setServletContext(container);
ServletRegistration.Dynamic servlet = container.addServlet(
"dispatcher", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
}
}
HibernateConfiguration.java
#Configuration
#EnableTransactionManagement
#ComponentScan({ "com.project.maven." })
#PropertySource(value = { "classpath:application.properties" })
public class HibernateConfiguration {
#Autowired
private Environment environment;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.project.maven.entity" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
AppConfig.java
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.project.maven")
public class AppConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
registry.addResourceHandler("**/**")
.addResourceLocations("classpath:/META-INF/resources/"); // harus ada folder resources di webapp/WEB-INF/
}
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
what about your other config !
send your controller class code
if you are sure about your config try with #GetMapping("/tesget")

flowExecutionUrl no redirect

I've followed some examples for redirecting in SWF and every do it equal. In my case the link don't redirect, execution reference don't change and url has changed to href's value. If I set it in a commandButton then the result is succes.
I use JSF 2.2 and SWF 2.3 on glassfish 4. Any suggestions> Thanks!
<a href="${flowExecutionUrl}&_eventId=TRANSITION_NAME" >
My link
<a href="${flowExecutionUrl}&_eventId=visit" >
URL result
http://localhost:8080/aio/spring/adminSpace?execution=e4s3&_eventId=visit
Flow definition
<view-state id="showEvent" view="list_events.xhtml">
<secured attributes="ROLE_MEMBER" />
<on-entry>
<evaluate expression="eventProvider.showEvents()" result="viewScope.pagesList"/>
</on-entry>
<transition on="pageCreated" to="newEvent" />
<transition on="visit" to="visitEvent"/>
</view-state>
<view-state id="newEvent" view="newEvent_1.xhtml">
<secured attributes="ROLE_MEMBER" />
<on-render>
<set name="pictureProvider.idRequest" value="'event'" />
</on-render>
<transition on="back" to="showEvent" />
<transition on="save" to="showEvent" />
<on-exit>
<evaluate expression="eventProvider.deleteTempComponents()" />
</on-exit>
</view-state>
<view-state id="visitEvent" view="event.xhtml">
</view-state>
WebFlowConfig class
#Configuration
public class WebFlowConfig extends AbstractFacesFlowConfiguration {
#Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry())
.addFlowExecutionListener(new FlowFacesContextLifecycleListener())
.addFlowExecutionListener(new SecurityFlowExecutionListener())
.build();
}
#Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder(flowBuilderServices())
.setBasePath("/WEB-INF/flows")
.addFlowLocationPattern("/**/*-flow.xml")
.build();
}
#Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
//.setViewFactoryCreator(new JsfViewFactoryCreator())
.setDevelopmentMode(true).build();
}
#Bean
public CustomScopeConfigurer customScopeConfigurer() {
Map<String, Object> scopes = new HashMap<String, Object>();
scopes.put("view", new ViewScope());
CustomScopeConfigurer configurer = new CustomScopeConfigurer();
configurer.setScopes(scopes);
return configurer;
}
}
WebMvcConfig class
#EnableWebMvc
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{
#Autowired
private WebFlowConfig webFlowConfig;
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/");
}
#Bean
public FlowHandlerMapping flowHandlerMapping() {
FlowHandlerMapping mapping = new FlowHandlerMapping();
mapping.setOrder(1);
mapping.setFlowRegistry(this.webFlowConfig.flowRegistry());
/* If no flow matches, map the path to a view, e.g. "/intro" maps to a view named "intro" */
mapping.setDefaultHandler(new UrlFilenameViewController());
return mapping;
}
#Bean
public FlowHandlerAdapter flowHandlerAdapter() {
JsfFlowHandlerAdapter adapter = new JsfFlowHandlerAdapter();
adapter.setFlowExecutor(this.webFlowConfig.flowExecutor());
return adapter;
}
#Bean
public UrlBasedViewResolver faceletsViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setViewClass(JsfView.class);
resolver.setPrefix("/WEB-INF/");
resolver.setSuffix(".xhtml");
return resolver;
}
#Bean
public SimpleControllerHandlerAdapter simpleControllerHandlerAdapter() {
return new SimpleControllerHandlerAdapter();
}
#Bean
public SessionLocaleResolver localeResolver(){
SessionLocaleResolver localeResolver=new SessionLocaleResolver();
localeResolver.setDefaultLocale(new Locale("es"));
return localeResolver;
}
#Bean
public ReloadableResourceBundleMessageSource messageSource(){
ReloadableResourceBundleMessageSource msg=new ReloadableResourceBundleMessageSource();
msg.setBasename("classpath*:error");
return msg;
}
#Bean
public StandardServletMultipartResolver multipartResolver(){
return new StandardServletMultipartResolver();
}
/*
#Bean
public LocaleChangeInterceptor localeChangeInterceptor(){
LocaleChangeInterceptor changeInterceptor=new LocaleChangeInterceptor();
changeInterceptor.setParamName("locale");
return changeInterceptor;
}
#Bean
public ControllerClassNameHandlerMapping nameHandlerMapping(){
ControllerClassNameHandlerMapping controller=new ControllerClassNameHandlerMapping();
Object[] obj={localeChangeInterceptor()};
controller.setInterceptors(obj);
return controller;
}*/
}

Spring WebFlow (seemingly) randomly stops working in Spring Boot app

I have a flow which seemed to be working fine until yesterday, when suddenly I started getting the following exception in my HTML page that maps to the first state in my flow:
org.springframework.expression.spel.SpelEvaluationException: EL1007E:(pos 0): Property or field 'flowScope' cannot be found on null
The offending line of code was:
<h3 th:text="${flowRequestContext.flowScope}"/>
Further investigation showed that none of the flow variables are available anymore. Furthermore if I put print statements into the Service which the flow makes various calls to, I can see that none of these methods are being called anymore - it's like the flow just isn't running at all.
This was working fine previously. I even reverted all of my local changes to a previously stable version of the code, and the same issue was happening there as well. The only thing that seemed to temporarily get around the problem was to restart my computer - the problem disappeared for a short while but then came back.
To be honest I'm completely out of ideas as to what could have started causing such an intermittent problem. I was thinking along the lines of a stale Java process running in the background interfering with future runs of the application, but have checked for and killed off any remaining process in between deploys to no avail.
I have included what I hope are the relevant file below. Any help resolving this issue would be very much appreciated.
checkout.xml
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<on-start>
<set name="flowScope.paymentMethods" value="checkoutWidgetService.getPaymentMethods()"/>
<set name="flowScope.deliveryAddress" value="checkoutWidgetService.getDeliveryAddress()"/>
<set name="flowScope.sessionId" value="externalContext.nativeRequest.session.id"/>
</on-start>
<view-state id="payment-methods" view="payment-methods">
<transition on="selectPaymentMethod" to="new-details">
<evaluate expression="checkoutWidgetService.getCardDetails(requestParameters.type)" result="flowScope.cardDetails"/>
</transition>
</view-state>
<view-state id="new-details" view="new-details">
<transition on="submitDetails" to="summary">
<evaluate expression="checkoutWidgetService.buildCardDetails(requestParameters)" result="flowScope.cardDetails"/>
</transition>
</view-state>
<view-state id="summary" view="summary">
<transition on="completeCheckout" to="redirect">
<evaluate expression="checkoutWidgetService.completeCheckout(externalContext.nativeRequest.session, flowRequestContext, flowScope.cardDetails)"/>
</transition>
<transition on="cancelCheckout" to="redirect">
<evaluate expression="checkoutWidgetService.cancelCheckout(externalContext.nativeRequest.session, flowRequestContext)"/>
</transition>
</view-state>
<end-state id="redirect" view="externalRedirect:contextRelative:/payments/checkout-widgets/end"/>
</flow>
WebflowConfig.java
#Configuration
#AutoConfigureAfter(MvcConfig.class)
public class WebflowConfig extends AbstractFlowConfiguration {
#Autowired
private SpringTemplateEngine templateEngine;
#Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry())
.addFlowExecutionListener(new SecurityFlowExecutionListener())
.build();
}
#Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder(flowBuilderServices())
.addFlowLocation("classpath:/templates/checkout.xml", "payments/checkout-widget/start")
.build();
}
#Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
.setViewFactoryCreator(mvcViewFactoryCreator())
.setDevelopmentMode(true)
.build();
}
#Bean
public FlowController flowController() {
FlowController flowController = new FlowController();
flowController.setFlowExecutor(flowExecutor());
return flowController;
}
#Bean
public FlowHandlerMapping flowHandlerMapping() {
FlowHandlerMapping flowHandlerMapping = new FlowHandlerMapping();
flowHandlerMapping.setFlowRegistry(flowRegistry());
flowHandlerMapping.setOrder(-1);
return flowHandlerMapping;
}
#Bean
public FlowHandlerAdapter flowHandlerAdapter() {
FlowHandlerAdapter flowHandlerAdapter = new FlowHandlerAdapter();
flowHandlerAdapter.setFlowExecutor(flowExecutor());
flowHandlerAdapter.setSaveOutputToFlashScopeOnRedirect(true);
return flowHandlerAdapter;
}
#Bean
public AjaxThymeleafViewResolver thymeleafViewResolver() {
AjaxThymeleafViewResolver viewResolver = new AjaxThymeleafViewResolver();
viewResolver.setViewClass(FlowAjaxThymeleafView.class);
viewResolver.setTemplateEngine(templateEngine);
return viewResolver;
}
#Bean
public MvcViewFactoryCreator mvcViewFactoryCreator() {
List<ViewResolver> viewResolvers = new ArrayList<>();
viewResolvers.add(thymeleafViewResolver());
MvcViewFactoryCreator mvcViewFactoryCreator = new MvcViewFactoryCreator();
mvcViewFactoryCreator.setViewResolvers(viewResolvers);
mvcViewFactoryCreator.setUseSpringBeanBinding(true);
return mvcViewFactoryCreator;
}
}
CheckoutWidgetSessionMvcController.java
#Controller
#RequestMapping("/payments/checkout-widgets")
public class CheckoutWidgetSessionMvcController {
#Inject
private CheckoutWidgetService service;
#RequestMapping(value = {"/start"}, method = RequestMethod.GET)
public ModelAndView paymentMethods() {
return new ModelAndView("payment-methods", null);
}
#RequestMapping(value = "/end", method = RequestMethod.GET)
public String invalidateSession(HttpSession session) {
service.invalidateSession(session);
return "dummy-redirect-post";
}
}
CheckoutWidgetService.java
public interface CheckoutWidgetService {
List<PaymentMethod> getPaymentMethods();
CardDetails getCardDetails(String name);
CardDetails buildCardDetails(LocalParameterMap params);
String getDeliveryAddress();
void completeCheckout(HttpSession session, RequestContext context, CardDetails cardDetails);
void cancelCheckout(HttpSession session, RequestContext context);
void invalidateSession(HttpSession session);
}
CheckoutWidgetServiceImpl.java
#Service("checkoutWidgetService")
public class CheckoutWidgetServiceImpl implements CheckoutWidgetService {
#Inject
private CheckoutWidgetSessionService sessionService;
private final List<PaymentMethod> paymentMethods = new ArrayList<>();
private final String deliveryAddress;
public CheckoutWidgetServiceImpl() {
paymentMethods.add(new PaymentMethod("PayPal", "/images/paypal-logo.png"));
paymentMethods.add(new PaymentMethod("Mastercard", "/images/mc-logo.png"));
paymentMethods.add(new PaymentMethod("Visa", "/images/visa-logo.png"));
paymentMethods.add(new PaymentMethod("Amex", "/images/amex-logo.png"));
paymentMethods.add(new PaymentMethod("Google Checkout", "/images/google-logo.png"));
deliveryAddress = "xxxxx";
}
#Override
public List<PaymentMethod> getPaymentMethods() {
System.out.println("Returning paymentMethods: " + paymentMethods);
return paymentMethods;
}
#Override
public CardDetails getCardDetails(String name) {
CardDetails cardDetails = new CardDetails();
cardDetails.setCardType(name);
return cardDetails;
}
#Override
public CardDetails buildCardDetails(LocalParameterMap params) {
CardDetails cardDetails = new CardDetails();
cardDetails.setCardNumber(params.get("cardNumber"));
cardDetails.setExpiryMonth(params.get("expiryMonth"));
cardDetails.setExpiryYear(params.get("expiryYear"));
cardDetails.setNameOnCard(params.get("nameOnCard"));
cardDetails.setCvv2(params.get("cvv2"));
return cardDetails;
}
#Override
public String getDeliveryAddress() {
return deliveryAddress;
}
#Override
public void invalidateSession(HttpSession session) {
session.invalidate();
}
private RedirectUrls getRedirectUrls(String sessionId) {
CheckoutWidgetSession widgetSession = sessionService.getCheckoutWidgetSession(sessionId).get();
return widgetSession.getRedirectUrls();
}
#Override
public void completeCheckout(HttpSession session, RequestContext context, CardDetails cardDetails) {
RedirectUrls redirects = getRedirectUrls(session.getId());
context.getFlowScope().remove("paymentMethods");
UriBuilder uriBuilder = UriBuilder.fromUri(URI.create(redirects.getSuccessUrl()));
String forwardUrl = uriBuilder.queryParam("transactionId", "12345").toString();
context.getFlowScope().put("forwardUrl", forwardUrl);
context.getFlowScope().put("target", "_top");
}
#Override
public void cancelCheckout(HttpSession session, RequestContext context) {
RedirectUrls redirects = getRedirectUrls(session.getId());
context.getFlowScope().remove("paymentMethods");
String forwardUrl = redirects.getCancelUrl();
context.getFlowScope().put("forwardUrl", forwardUrl);
context.getFlowScope().put("target", "_top");
}
}
Application.java
#EnableAutoConfiguration
#ComponentScan(basePackages = {"com.pay.widgets.checkout"})
#Import(JerseyAutoConfiguration.class)
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Okay this was a really stupid mistake on my part, the problem turned out to be down to a typo in the #RequestParameter annotation on the Controller:
payments/checkout-widgets
Which didn't line up with what was in the WebflowConfig defined flowRegistry:
payments/checkout-widget
I can only assume the resource was cached by Tomcat which is why it took so long for the issue to manifest and threw me off the scent in terms of suspecting my own changes to be responsible.

SPRING BOOT access to entityManager

I'm trying to update a project made with spring and hibernate with springboot.
Everything seems ok, but I can't figure how to get the entityManager.
I'm not using spring data, so no domain nor repository is used.
In this project, services are annotated with #service and entityManager is autowire with: #PersistenceContext,
here an example of my service
#Service
#Transactional
public class UserServiceImpl implements UserDetailsService, UserService {
#PersistenceContext
EntityManager entityManager;
/**
*
*/
private static final long serialVersionUID = 6384460058124202695L;
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
User user = entityManager.find(User.class, username);
return user;
}
The problem here is that the entityManager is null. So I read in doc that if we want to manage the entityManager we have to configure it, so I did this in configuration file:
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "services" });
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
The application is launching, but still have the entityManager null.
Any clue?
Edit: adding my application class (Has it's a demo project, I put all the config in one file)
#Configuration
#EnableAutoConfiguration
#ComponentScan
#EnableWebMvcSecurity
public class Application extends WebSecurityConfigurerAdapter{
#Value("${sec.cas.server}")
private String casServer;
#Value("${sec.app.server}")
private String appServer;
#Value("${spring.datasource.driverClassName}")
private String databaseDriverClassName;
#Value("${spring.datasource.url}")
private String databaseUrl;
#Value("${spring.datasource.username}")
private String databaseUsername;
#Value("${spring.datasource.password}")
private String databasePassword;
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
}
#Bean
public ComboPooledDataSource dataSource() {
ComboPooledDataSource datasource = new ComboPooledDataSource();
try {
datasource.setDriverClass(databaseDriverClassName);
} catch (PropertyVetoException e) {
throw new IllegalArgumentException("Wrong driver class");
}
datasource.setJdbcUrl(databaseUrl);
datasource.setUser(databaseUsername);
datasource.setPassword(databasePassword);
datasource.setAcquireIncrement(1);
datasource.setIdleConnectionTestPeriod(600);
datasource.setMaxPoolSize(500);
datasource.setMinPoolSize(50);
datasource.setMaxStatements(0);
datasource.setMaxConnectionAge(600);
datasource.setMaxIdleTime(600);
return datasource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
DefaultPersistenceUnitManager unitManager = new DefaultPersistenceUnitManager ();
unitManager.setDefaultDataSource(dataSource());
unitManager.setPersistenceXmlLocations("classpath*:META-INF/persistence.xml"); //location of your persistence.xml file
unitManager.setPackagesToScan(new String[] { "services" });
unitManager.setDefaultPersistenceUnitName("entityManager");
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setPersistenceUnitManager(unitManager);
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.show_sql", "false");
properties.setProperty("hibernate.format_sql", "true");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle9iDialect");
return properties;
}
#Bean
public JdbcDaoImpl jdbcUserService() {
JdbcDaoImpl jdbcDaoImpl = new JdbcDaoImpl();
jdbcDaoImpl.setEnableGroups(true);
jdbcDaoImpl.setEnableAuthorities(true);
jdbcDaoImpl.setDataSource(dataSource());
return jdbcDaoImpl;
}
#Bean
public ServiceProperties serviceProperties() {
ServiceProperties serviceProperties = new ServiceProperties();
serviceProperties.setService("http://"+appServer+"/j_spring_cas_security_check");
serviceProperties.setSendRenew(false);
return serviceProperties;
}
#Bean
public CasAuthenticationProvider casAuthenticationProvider() {
CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
casAuthenticationProvider.setAuthenticationUserDetailsService(authenticationUserDetailsService());
casAuthenticationProvider.setUserDetailsService(new UserServiceImpl());
//casAuthenticationProvider.setAuthenticationUserDetailsService(userServiceImpl.class);
casAuthenticationProvider.setServiceProperties(serviceProperties());
casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
casAuthenticationProvider.setKey("an_id_for_this_auth_provider_only");
return casAuthenticationProvider;
}
#Bean
public UserDetailsByNameServiceWrapper authenticationUserDetailsService() {
UserDetailsByNameServiceWrapper userDetailsByName = new UserDetailsByNameServiceWrapper();
userDetailsByName.setUserDetailsService(jdbcUserService());
return userDetailsByName;
}
#Bean
public Cas20ServiceTicketValidator cas20ServiceTicketValidator() {
Cas20ServiceTicketValidator casServiceTicketValidator = new Cas20ServiceTicketValidator("https://"+casServer+"/cas");
casServiceTicketValidator.setProxyCallbackUrl("http://"+appServer+"/");
casServiceTicketValidator.setProxyGrantingTicketStorage(new ProxyGrantingTicketStorageImpl());
return casServiceTicketValidator;
}
#Bean
public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
casAuthenticationFilter.setAuthenticationManager(authenticationManager());
casAuthenticationFilter.setAuthenticationSuccessHandler(new SavedRequestAwareAuthenticationSuccessHandler());
casAuthenticationFilter.setProxyGrantingTicketStorage(new ProxyGrantingTicketStorageImpl());
casAuthenticationFilter.setProxyReceptorUrl("/secure/receptor");
return casAuthenticationFilter;
}
#Bean
public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {
CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
casAuthenticationEntryPoint.setLoginUrl("https://"+casServer+"/cas/login");
casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
return casAuthenticationEntryPoint;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilter(casAuthenticationFilter());
http
.exceptionHandling()
.authenticationEntryPoint(casAuthenticationEntryPoint());
http
.authorizeRequests()
.antMatchers("/", "/home").authenticated()
.anyRequest().authenticated();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(casAuthenticationProvider());
}
Your EntityManager being null indicates that Spring isn't processing #PersistenceContext annotations in your UserServiceImpl instance.
You're creating an instance of UserServiceImpl manually as part of configuring your CasAuthenticationProvider bean. That means that Spring knows nothing about the instance and will not inject any of its dependencies. You need to use a Spring-created instance, for example by making it an argument of the casAuthenticationProvider() method.
Try:
DefaultPersistenceUnitManager unitManager = new DefaultPersistenceUnitManager();
unitManager.setPersistenceXmlLocations("classpath*:META-INF/persistence.xml"); //location of your persistence.xml file.
unitManager.setDefaultDataSource(dataSource);
In persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="entityManager" transaction-type="RESOURCE_LOCAL">
//classes, etc...
</persistence-unit>
</persistence>
and:
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setPersistenceUnitManager(unitManager);
em.setPersistenceUnitName("entityManager");
And then injet:
#PersistenceContext(unitName = "entityManager")
private EntityManager entityManager;
That should work.
Solution by OP.
Got it finally worked, no entityManager is needed to be redefined, just add the bean who get the #persistenceContext (before spring boot 1.2.0)
Here is my application context:
#Configuration
#ComponentScan(basePackages={"services","model"})
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
#Bean
public PersistenceAnnotationBeanPostProcessor persistenceBeanPostProcessor() {
return new PersistenceAnnotationBeanPostProcessor();
}

Configuring a Conversion Service with a custom DateFormatter

I'm trying to add a custom DateFormatter to my spring/thymeleaf application, with the help of the following documentation :
http://www.thymeleaf.org/doc/html/Thymeleaf-Spring3.html#conversions-utility-object
The problem is that I don't use xml configuration for my beans definitions, but a WebConfig.java class with the following implementation :
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"com.myapp.web.controller","net.atos.wfs.wts.adminportal.web.domain"})
public class WebConfig extends WebMvcConfigurerAdapter {
private static final Logger LOG = LoggerFactory.getLogger(WebConfig.class);
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
registry.addInterceptor(localeChangeInterceptor);
}
#Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
cookieLocaleResolver.setDefaultLocale(StringUtils.parseLocaleString("en"));
return cookieLocaleResolver;
}
#Bean
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
//NB, selecting HTML5 as the template mode.
resolver.setTemplateMode("HTML5");
resolver.setCacheable(false);
return resolver;
}
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
engine.setMessageResolver(messageResolver());
engine.addDialect(new LayoutDialect());
return engine;
}
#Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
viewResolver.setOrder(1);
viewResolver.setViewNames(new String[]{"*"});
viewResolver.setCache(false);
return viewResolver;
}
#Bean
public IMessageResolver messageResolver() {
SpringMessageResolver messageResolver = new SpringMessageResolver();
messageResolver.setMessageSource(messageSource());
return messageResolver;
}
#Override
public void addFormatters(FormatterRegistry registry) {
super.addFormatters(registry);
registry.addFormatter(new DateFormatter());
}
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("/WEB-INF/messages/messages");
// if true, the key of the message will be displayed if the key is not
// found, instead of throwing a NoSuchMessageException
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
// # -1 : never reload, 0 always reload
messageSource.setCacheSeconds(0);
return messageSource;
}
}
And here is the code of my Custom DateFormatter :
public class DateFormatter implements Formatter<Date> {
#Autowired
private MessageSource messageSource;
public DateFormatter() {
super();
}
public Date parse(final String text, final Locale locale) throws ParseException {
final SimpleDateFormat dateFormat = createDateFormat(locale);
return dateFormat.parse(text);
}
public String print(final Date object, final Locale locale) {
final SimpleDateFormat dateFormat = createDateFormat(locale);
return dateFormat.format(object);
}
private SimpleDateFormat createDateFormat(final Locale locale) {
//The following line is not working (nullPointerException on messageSource)
//final String format = this.messageSource.getMessage("date.format", null, locale);
//The following line is working :
final String format = "dd/MM/yyyy";
final SimpleDateFormat dateFormat = new SimpleDateFormat(format);
dateFormat.setLenient(false);
return dateFormat;
}
}
My question is : how can I add a custom formatter that will be able to use #Autowired elements ?
The xml configuration is this one :
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
...
<mvc:annotation-driven conversion-service="conversionService" />
...
<!-- **************************************************************** -->
<!-- CONVERSION SERVICE -->
<!-- Standard Spring formatting-enabled implementation -->
<!-- **************************************************************** -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<set>
<bean class="thymeleafexamples.stsm.web.conversion.VarietyFormatter" />
<bean class="thymeleafexamples.stsm.web.conversion.DateFormatter" />
</set>
</property>
</bean>
...
</beans>
I tried to uset the following configuration in WebConfig class :
#Bean
public FormattingConversionServiceFactoryBean conversionService() {
FormattingConversionServiceFactoryBean conversionService = new FormattingConversionServiceFactoryBean();
Set<Formatter<?>> formatters = new TreeSet<Formatter<?>>();
formatters.add(new DateFormatter());
conversionService.setFormatters(formatters);
return conversionService;
}
But in this case, the formatter is not taken into account in my application.
Thanks in advance,
Antoine.
Add this to your WebMvcConfigurerAdapter
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(dateFormatter);
}
#Autowired
private DateFormatter dateFormatter;
#Bean
public DateFormatter dateFormatter() {
return new DateFormatter("dd/MM/yyyy");
}
I used the following configuration class and was able to get the custom formatter to be called. I have not been able to get the messageSource to be passed in, it is always null as the auto-configure bean is created later in the application startup.
#Configuration
public class ThymeleafConfig {
#Autowired
private MessageSource messageSource;
#Bean
public SpringSecurityDialect securityDialect() {
return new SpringSecurityDialect();
}
#Bean
public ConversionService conversionService() {
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService( false );
conversionService.addFormatter( dateFormatter() );
return conversionService;
}
#Bean
public DateFormatter dateFormatter() {
return new DateFormatter( messageSource );
}
}
You also need to make sure in your template that you use the double brackets around the field. i.e.
<td th:text="${{user.createDate}}">12-MAR-2015</td>

Resources