FreeMarker using javax.json.JsonObject as Data Model - freemarker

I am testing FreeMarker
Maven dependencies:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
</dependencies>
Simple class User:
public class User {
private String firstName;
private String lastName;
private String email;
public User(String firstName, String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Simple FreeMarker file (basicJson.ftl):
Name: ${user.firstName} ${user.lastName}
Class for create a Configuration:
import java.io.File;
import java.io.IOException;
import freemarker.template.Configuration;
import freemarker.template.TemplateExceptionHandler;
public class FreemarkerConfigurationFactory {
public static Configuration newFreemarkerConfiguration() throws IOException {
Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
cfg.setDirectoryForTemplateLoading(new File("./templates/tests/"));
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
cfg.setLogTemplateExceptions(false);
return cfg;
}
}
Test class:
import static org.junit.Assert.assertEquals;
import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import javax.json.Json;
import javax.json.JsonObject;
import org.junit.Before;
import org.junit.Test;
import freemarker.template.Configuration;
import freemarker.template.Template;
public class FreemarkerJsonTest {
private Configuration cfg;
private ByteArrayOutputStream output;
private Template template;
private Writer writer;
private Map<String, Object> map;
#Before
public void setUp() throws Exception {
cfg = FreemarkerConfigurationFactory.newFreemarkerConfiguration();
output = new ByteArrayOutputStream();
writer = new OutputStreamWriter(output);
map = new HashMap<>();
}
#Test
public void objectTest() throws Exception {
User user = new User("Clarice", "Leman", "clarice.leman#domain.com");
map.put("user", user);
String outputString = process("basicJson.ftl", map);
assertEquals("Name: Clarice Leman", outputString);
}
#Test
public void jsonTest() throws Exception {
JsonObject jsonUser = Json.createObjectBuilder()
.add("id", 10)
.add("firstName", "Clarice")
.add("lastName", "Leman")
.add("email", "clarice.leman#domain.com")
.build();
map.put("user", jsonUser);
String outputString = process("basicJson.ftl", map);
assertEquals("Name: Clarice Leman", outputString);
}
private String process(String templateName, Object root) throws Exception {
template = cfg.getTemplate(templateName);
template.process(root, writer);
return output.toString();
}
}
The question is that the test "objectTest()" passes but the test "jsonTest()" no, because it produces a String:
Name: "Clarice" "Leman"
Using a Online FreeMarker Template (http://freemarker-online.kenshoo.com/):
Template:
Name: ${user.firstName} ${user.lastName}
Data Model:
user = {"firstName":"Clarice","lastName":"Leman","email":"clarice.leman#domain.com"}
Result
Name: Clarice Leman

The JSON you enter on FreeMarker Online is transformed to List-s and Map-s by FreeMarker Online before passed to FreeMarker itself. The syntax of that whole box is specific to that online service. So if you have JSON to show, either it has to be converted to a something that the default ObjectWrapper of FreeMarker already understands, or the ObjectWrapper has to be extended to understand javax.json classes. (But often, you bind the JSON to some application-specific classes anyway, and those often already use JavaBeans conventions and List-s, which the default ObjectWrapper understands.)

Related

How to set target type in Spring batch if CSV format is not fixed in all batch execution cycle?

I am trying read a CSV file using spring batch . I am using FlatFileItemReader. Batch execution is chunk based.
But the issue is CSV format is not fixed in each batch execution cycle.
For example ,
In 1st Cycle- Let's say I have a CSV which has header as id, firstName, LastName.
In 2nd Cycle - It can have header as name, address, salary.
I want to save data for csv in Key-Value pair in one column.(For each row in CSV ,a row will be saved in DB.)
How to implement reader,processer,writer for this?
Reader Class for fixed format i have implemented as below:
public class Reader {
public static FlatFileItemReader<Customer> reader(String path) {
FlatFileItemReader<Customer> reader = new FlatFileItemReader<Customer>();
reader.setResource(new ClassPathResource(path));
reader.setLineMapper(new DefaultLineMapper<Customer>() {
{
setLineTokenizer(new DelimitedLineTokenizer() {
{
setNames(new String[] { "id", "firstName", "lastName" });
}
});
setFieldSetMapper(new BeanWrapperFieldSetMapper<Customer>() {
{
setTargetType(Customer.class);
}
});
}
});
return reader;
}
}
For Writer
public class Writer implements ItemWriter<Customer> {
private final CustomerDao customerDao;
public Writer(CustomerDao customerDao) {
this.customerDao = customerDao;
}
#Override
public void write(List<? extends Customer> customers) throws Exception {
customerDao.insert(customers);
}
}
For BatchCOnfig
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.javasampleapproach.batchcsvpostgresql.dao.CustomerDao;
import com.javasampleapproach.batchcsvpostgresql.model.Customer;
import com.javasampleapproach.batchcsvpostgresql.step.Listener;
import com.javasampleapproach.batchcsvpostgresql.step.Processor;
import com.javasampleapproach.batchcsvpostgresql.step.Reader;
import com.javasampleapproach.batchcsvpostgresql.step.Writer;
#Configuration
#EnableBatchProcessing
public class BatchConfig {
#Autowired
public JobBuilderFactory jobBuilderFactory;
#Autowired
public StepBuilderFactory stepBuilderFactory;
#Autowired
public CustomerDao customerDao;
#Bean
public Job job() {
return jobBuilderFactory.get("job").incrementer(new RunIdIncrementer()).listener(new Listener(customerDao))
.flow(step1()).end().build();
}
#Bean
public Step step1() {
return stepBuilderFactory.get("step1").<Customer, Customer>chunk(2)
.reader(Reader.reader("customer-data.csv"))
.processor(new Processor()).writer(new Writer(customerDao)).build();
}
}
Customer DTO is as below
public class Customer {
private long id;
private String firstName;
private String lastName;
public Customer() {
}
public Customer(long id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
Spring Batch - Is it possible to have a dynamic column in FlatFileReader?
This question is similar to my question but i am unable to understand the answer.

Spring Boot PATCH MongoDB

{
"id": "5e6a5f98003bb209b536a1be",
"firstName": "Alice",
"lastName": "Smith"
}
#Document
public class Customer {
#Id
public String id;
public String firstName;
public String lastName;
public Customer() {}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
#Override
public String toString() {
return String.format(
"Customer[id=%s, firstName='%s', lastName='%s']",
id, firstName, lastName);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
If I am trying to update ONLY last name with below JSON body- firstName is getting set to NULL .. How can I avoid that ?
that is .. update ONLY what is in the request body ..don't set missing attributes to null.
I am using #PatchMapping("/customer/update")
{
"id": "5e6a5f98003bb209b536a1be",
"lastName": "Smith1"
}
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.HandlerMapping;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
#Component
public class PartialUpdateArgumentResolver implements HandlerMethodArgumentResolver {
XmlMapper xmlMapper= new XmlMapper();
#Autowired ApplicationContext context;
#Override
public boolean supportsParameter(MethodParameter parameter) {
RequestMapping methodAnot = parameter.getMethodAnnotation(RequestMapping.class);
if( methodAnot == null ) return false;
if( !Arrays.asList(methodAnot.method()).contains(RequestMethod.PATCH) ) return false;
return parameter.hasParameterAnnotation(PatchRequestBody.class);
}
#Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
ServletServerHttpRequest req = createInputMessage(webRequest);
Patch patch = parameter.getMethodAnnotation(Patch.class);
Class serviceClass = patch.service();
Class idClass = patch.id();
Object service = context.getBean(serviceClass);
String idStr = getPathVariables(webRequest).get("id");
Object id = idClass.cast(idStr);
Method method = ReflectionUtils.findMethod(serviceClass, "find", idClass);
Object obj = ReflectionUtils.invokeMethod(method, service, id);
obj = readJavaType(obj, req);
return obj;
}
private Map<String, String> getPathVariables(NativeWebRequest webRequest) {
HttpServletRequest httpServletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
return (Map<String, String>) httpServletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
}
protected ServletServerHttpRequest createInputMessage(NativeWebRequest webRequest) {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
return new ServletServerHttpRequest(servletRequest);
}
private Object readJavaType(Object object, HttpInputMessage inputMessage) {
try {
return this.xmlMapper.readerForUpdating(object).readValue(inputMessage.getBody());
}
catch (IOException ex) {
throw new HttpMessageNotReadableException("Could not read document: " + ex.getMessage(), ex);
}
}
}

Not supported for DML operations .Unable to update data in postgresql database using spring data

Hi I am using spring boot and Spring data i want to fetch data from database on the basis of id but m not able to retreive it.
M getting this error "exception":
"org.springframework.dao.InvalidDataAccessApiUsageException",
"message": "org.hibernate.hql.internal.QueryExecutionRequestException:
Not supported for DML operations [Update
com.ge.health.poc.model.SpringModel SET name='sneha' where id=?];
nested exception is java.lang.IllegalStateException:
org.hibernate.hql.internal.QueryExecutionRequestException: Not
supported for DML operations [Update
com.ge.health.poc.model.SpringModel SET name='sneha' where id=?]",
"path": "/updatedata"
}
Main Class
package com.ge.health.poc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringDataApplication {
public static void main(String[] args) {
SpringApplication.run(SpringDataApplication.class, args);
}
}
Controller Class
package com.ge.health.poc.controller;
import java.io.IOException;
import java.text.ParseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ge.health.poc.model.SpringModel;
import com.ge.health.poc.service.BookServiceImpl;
#RestController
public class SpringController {
#Autowired
BookServiceImpl bookserviceimpl;
#RequestMapping(value = "/insertdata", method = RequestMethod.POST)
#ResponseBody
public void helloService(#RequestBody String input, final RedirectAttributes redirectAttributes)
throws JsonParseException, JsonMappingException, IOException, ParseException {
System.out.println(input);
ObjectMapper mapper = new ObjectMapper();
SpringModel pojodata = mapper.readValue(input, SpringModel.class);
System.out.println(pojodata);
System.out.println(pojodata.getAuthor());
bookserviceimpl.save(pojodata);
}
#RequestMapping(value = "/getdata/{id}")
#ResponseBody
public void retreiveData(#PathVariable("id") int id)
throws JsonParseException, JsonMappingException, IOException, ParseException {
System.out.println("id is:" + id);
bookserviceimpl.retreive(id);
}
#RequestMapping(value = "/deletedata", method = RequestMethod.DELETE)
#ResponseBody
public void deleteData(#RequestBody String id)
throws JsonParseException, JsonMappingException, IOException, ParseException {
System.out.println("M in delete");
System.out.println(id);
ObjectMapper mapper = new ObjectMapper();
SpringModel pojodata = mapper.readValue(id, SpringModel.class);
int idd = (pojodata.getId());
System.out.println("value oof idd is:" + idd);
System.out.println("M into delete method");
bookserviceimpl.delete(idd);
}
#RequestMapping(value = "/updatedata", method = RequestMethod.PUT)
#ResponseBody
public void updateData(#RequestBody String id)
throws JsonParseException, JsonMappingException, IOException, ParseException {
System.out.println("M in update");
System.out.println(id);
ObjectMapper mapper = new ObjectMapper();
SpringModel pojodata = mapper.readValue(id, SpringModel.class);
int idd = (pojodata.getId());
System.out.println("value oof idd is:" + idd);
bookserviceimpl.update(idd);
}
}
Repository
package com.ge.health.poc.interfac;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.ge.health.poc.model.SpringModel;
#Repository
#Transactional
public interface BookRepository extends JpaRepository<SpringModel, Long> {
#Query("select author from SpringModel where id=?")
String findName(int id);
#Query("Update SpringModel SET name='sneha' where id=?")
String UpdateByID(int id);
#Query("delete from SpringModel where id=?")
String deleteById(int id);
}
BookServiceImpl.java
package com.ge.health.poc.service;
import javax.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ge.health.poc.interfac.BookRepository;
import com.ge.health.poc.model.SpringModel;
#Component
public class BookServiceImpl implements BookService {
#Autowired
EntityManager entitymanager;
#Autowired
BookRepository bookrepo;
#Override
public void save(SpringModel bookdata) {
bookrepo.save(bookdata);
}
public String retreive(int id) {
String s = bookrepo.findName(id);
System.out.println("Author name is:" + s);
return null;
}
public void delete(int id) {
System.out.println("M into service delete method");
bookrepo.deleteById(id);
}
public void update(int id) {
System.out.println("M in service update");
bookrepo.UpdateByID(id);
}
}
this is model class
package com.ge.health.poc.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "spring_model")
public class SpringModel {
#Id
private Long id;
#Column
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column
private String isbn;
#Override
public String toString() {
return "SpringModel [id=" + id + ", name=" + name + ", isbn=" + isbn + ", author=" + author + ", pages=" + pages
+ "]";
}
#Column
private String author;
#Column
private String pages;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPages() {
return pages;
}
public void setPages(String pages) {
this.pages = pages;
}
}
Try the annotation #Modifying(org.springframework.data.jpa.repository.Modifying) on the repository methods and #Transactional(org.springframework.transaction.annotation.Transactional) in service implementation which does DML operation. please refer this answer for more information.
By Default spring jpa will think query is select query.So, To make sure the query is updating the existed row for a particular entity
add #modifying Annotation on the method which is updating the existed row
This might works for you

How to turn on annotation driven validation in Spring 4?

I am using the annotation validation as below:
public String processRegistration(#Valid Spitter spitter, Errors errors,
Model model) {
if (errors.hasErrors()) {
return "registerForm";
}
...
}
But the errors.hasErrors() always return false. I guess I didn't turn on some kind of switch for the annotation driven validation. But how can I do it with JavaConfig in Spring 4? I tried to apply the #AnnotationDrivenConfig to the configuration class, but that type cannot even be resolved.
ADD 1
I already have the following configuration in the servlet-context.xml, but still doesn't work.
<annotation-driven />
ADD 2
The spitter.java:
package com.learnspring.mvc.web;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hibernate.validator.constraints.Email;
public class Spitter {
private Long id;
#NotNull
#Size(min = 5, max = 16)
private String username="default name";
#NotNull
#Size(min = 5, max = 25)
private String password;
#NotNull
#Size(min = 2, max = 30)
private String firstName;
#NotNull
#Size(min = 2, max = 30)
private String lastName;
#NotNull
#Email
private String email;
public Spitter() {
}
public Spitter(String username, String password, String firstName,
String lastName, String email) {
this(null, username, password, firstName, lastName, email);
}
public Spitter(Long id, String username, String password, String firstName,
String lastName, String email) {
this.id = id;
this.username = username;
this.password = password;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
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;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Override
public boolean equals(Object that) {
return EqualsBuilder.reflectionEquals(this, that, "firstName",
"lastName", "username", "password", "email");
}
#Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this, "firstName",
"lastName", "username", "password", "email");
}
}
The SpitterController.java
package com.learnspring.mvc.web;
import static org.springframework.web.bind.annotation.RequestMethod.*;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import com.learnspring.mvc.web.Spitter;
import com.learnspring.mvc.web.SpitterRepository;
#Controller
#RequestMapping("/spitter")
public class SpitterController {
private SpitterRepository spitterRepository;
#Autowired
public SpitterController(SpitterRepository spitterRepository) {
this.spitterRepository = spitterRepository;
}
#RequestMapping(value = "/register", method = GET)
public String showRegistrationForm(Model model) {
model.addAttribute("spitter", new Spitter());
return "registerForm";
}
#RequestMapping(value = "/register", method = POST)
public String processRegistration(#Valid Spitter spitter,
Errors errors, Model model) {
if (errors.hasErrors()) {
return "registerForm";
}
if (spitter == null) {
model.addAttribute("ufo", "spitter is null!");
model.addAttribute("mark", "MARKER");
return "forward:/spitter/spitter/registerFail";
}
else if (!spitter.getUsername().contains("ufo")) {
model.addAttribute("ufo", "spitter user name is not ufo!!");
model.addAttribute("mark", "MARKER:" + spitter.getUsername());
model.addAttribute("pwd", "MARKER:" + spitter.getPassword());
return "forward:/spitter/spitter/registerFail";
}
else
return "redirect:/spitter/spitter/registerOK";
}
#RequestMapping(value = "/{username}", method = GET)
public String showSpitterProfile(#PathVariable String username, Model model) {
Spitter spitter = spitterRepository.findByUsername(username);
model.addAttribute(spitter);
return "profile";
}
#RequestMapping(value = "/spitter/registerOK", method = GET)
public String showRegisterOK() {
return "registerOK";
}
#RequestMapping(value = "/spitter/registerFail", method = POST)
public String showRegisterFail() {
return "registerFail";
}
}
The registerForm.jsp:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib uri="http://www.springframework.org/tags/form" prefix="f" %>
<%# page session="false" %>
<html>
<head>
<title>Spitter</title>
<link rel="stylesheet" type="text/css"
href="<c:url value="/resources/style.css" />" >
</head>
<body>
<h1>Register</h1>
<f:form method="POST" commandName="spitter">
f:First Name: <f:input path="firstName" /><br/>
f-Last Name: <f:input path="lastName" /><br/>
f-Email: <f:input path="email" /><br/>
f-User Name: <f:input path="username" /><br/>
f-Password: <f:input path="password" /><br/>
<input type="submit" value="Register" />
</f:form>
</body>
</html>
The WebConfig.java:
package com.learnspring.mvc.web;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#EnableWebMvc
#ComponentScan("com.learnspring.mvc.web")
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// TODO Auto-generated method stub
super.addResourceHandlers(registry);
}
}
The RootConfig.java
package com.learnspring.mvc.config;
import java.util.regex.Pattern;
import com.learnspring.mvc.config.RootConfig.WebPackage;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Import;
import org.springframework.core.type.filter.RegexPatternTypeFilter;
#Configuration
#ComponentScan(basePackages = { "com.learnspring.mvc" }, excludeFilters = { #Filter(type = FilterType.CUSTOM, value = WebPackage.class) })
public class RootConfig {
public static class WebPackage extends RegexPatternTypeFilter {
public WebPackage() {
super(Pattern.compile("com.learnspring.mvc\\.web"));
}
}
}
The SpitterWebInitialization.java
package com.learnspring.mvc.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.learnspring.mvc.config.RootConfig;
import com.learnspring.mvc.web.WebConfig;
public class SpitterWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
ADD 3
And the web.xml: (Actually, everything is commented out.)
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<!--
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
-->
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<!--
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
-->
<!-- Processes application requests -->
<!--
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
-->
</web-app>
Judging from your explanation and the following error java.lang.ClassNotFoundException: javax.validation.Validator Spring doesn't see the classes and as such doesn't enable JSF-303 validation.
Make sure that the correct jars are on the classpath and that you have an implementation as well. When using maven adding something like the following should do the trick.
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.3.Final</version>
</dependency>
This will add the needed jars to the WEB-INF/lib directory which in turn lets Spring Web MVC detect it and configure the appropriate bean.
For an explanations of the different annotations you might want to check In Hibernate Validator 4.1+, what is the difference between #NotNull, #NotEmpty, and #NotBlank?.
I see two points in your code that may cause de problem.
1) Instead of <annotation-driven /> use the correct namespace <mvc:annotation-driven/>.
2) On your #Controller change your functions parameters from:
public String processRegistration(#Valid Spitter spitter, Errors errors,
Model model) {
if (errors.hasErrors()) {
return "registerForm";
}
...
To:
public String processRegistration(#ModelAttribute("spitter") #Valid Spitter spitter, BindingResult result) {
if (result.hasErrors()) {
return "registerForm";
}
...
Try it! ;)

Spring Data ElasticSearch NullPointerException

I have just started with Spring Data ElasticSearch. I have implemented my own repository, but I get a null pointer exception if I try to save an entity. I have got the following code, this is only some test code.
package org.test.elasticsearch.models;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
#Document(indexName = "test", type = "book", shards = 1, replicas = 0)
public class Book {
#Id
private String id;
private String title;
private String author;
public Book(final String id, final String title, final String author) {
this.id = id;
this.title = title;
this.author = author;
}
public String getId() {
return this.id;
}
public void setId(final String id) {
this.id = id;
}
public String getTitle() {
return this.title;
}
public void setTitle(final String title) {
this.title = title;
}
public String getAuthor() {
return this.author;
}
public void setAuthor(final String author) {
this.author = author;
}
}
package org.test.elasticsearch.configs;
import org.elasticsearch.node.NodeBuilder;
import org.test.elasticsearch.repositories.implementations.BookRepositoryImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
#Configuration
#EnableElasticsearchRepositories("org.test.elasticsearch.repositories")
public class ElasticsearchConfiguration {
#Bean
public ElasticsearchOperations elasticsearchTemplate() {
final NodeBuilder nodeBuilder = new NodeBuilder();
return new ElasticsearchTemplate(nodeBuilder.local(true).clusterName("elasticsearch").node().client());
}
#Bean
public BookRepositoryImpl bookRepositoryImplementation() {
return new BookRepositoryImpl();
}
}
package org.test.elasticsearch.repositories;
import org.test.elasticsearch.models.Book;
import org.springframework.data.elasticsearch.repository.ElasticsearchCrudRepository;
public interface BookRepository extends ElasticsearchCrudRepository<Book, String>, BookRepositoryCustom {
// query methods
}
package org.test.webapp;
import org.test.elasticsearch.models.Book;
import org.test.elasticsearch.models.Book.BookBuilder;
import org.test.elasticsearch.repositories.BookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class Test {
#Autowired
static BookRepository BookRepository;
public static void main(final String[] args) {
SpringApplication.run(test.class, args);
final Book testBook = new Book("12345", "TestTitle", "TestAuthor");
BookRepository.save(testBook);
}
}
That's my code. And I get the following message after running my spring boot application.
Exception in thread "main" java.lang.NullPointerException
at org.test.webapp.test.main(Test.java:24)
Does anyone have an idea? And another question: When should I use ElasticsearchTemplate with IndexQuery over a custom repository to save my entities?
Your problem is, actually, with Spring Boot: you are not using it properly. Your Test class should look like this (no "static" access to BookRepository and done differently):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.test.elasticsearch.models.Book;
import org.test.elasticsearch.repositories.BookRepository;
#Configuration
#ComponentScan(basePackages = {"org.test.elasticsearch.configs", "org.test.webapp"})
#EnableAutoConfiguration
public class Test implements CommandLineRunner {
#Autowired
private BookRepository bookRepository;
#Override
public void run(String... args) {
final Book testBook = new Book("12345", "TestTitle", "TestAuthor");
bookRepository.save(testBook);
}
public static void main(final String[] args) {
SpringApplication.run(Test.class, args);
}
}
Because, as I see it, you don't want to use a web application, so further you only need these dependencies in pom.xml. Nothing related to spring-boot-web:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>

Resources