How to pass a MultipartHttpServletRequest? - spring

Before posting this, I searched on stack overflow and did the applicable answer. I tried putting enctype on my form tag,
<form name="something" method="post" enctype="multipart/form-data">
adding MultipartResolver on my bean,
<bean id="spring.RegularCommonsMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
but none of these solved my problem.
I want a method that accepts MultipartHttpServletRequest as the parameter. But the browser console gives me this error:
POST link.json 500 Internal Server Error
Eclipse on the other hand throws this error:
Servlet.service() for servlet [action] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: Current request is not of type [org.springframework.web.multipart.MultipartHttpServletRequest]
My controller code looks like this:
#RequestMapping("myjson/myLink")
public void myMethod(MultipartHttpServletRequest request)
{
}
My code accepts HttpServletRequest and not MultipartHttpServletRequest. Is there other way to this?
I badly need MultipartHttpServletRequest because of its getFile method. I need to get an image from the client and store it on the server.

This will surely work for you.
HTML:
<form action="myjson/myLink" id="fileForm" method="POST" enctype="multipart/form-data">
<input type="file" name="File"/>
</form>
Controller:
#RequestMapping(value = "/myjson/myLink", method = RequestMethod.POST)
public #ResponseBody String SaveFile(HttpServletRequest request, #RequestParam("File") MultipartFile file) {
if(!file.isEmpty())
{
try
{
File convFile = new File(//here file location+filename);
convFile.createNewFile();
FileOutputStream fos = new FileOutputStream(convFile);
fos.write( file.getBytes() );
fos.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
Spring Configuration:
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"/>
and in your Spring Initializer class Define MultipartConfigElement element
public class SpringInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SpringConfiguration.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
registration.setMultipartConfig(getMultipartConfigElement());
}
private MultipartConfigElement getMultipartConfigElement() {
MultipartConfigElement multipartConfigElement = new MultipartConfigElement( LOCATION, MAX_FILE_SIZE, MAX_REQUEST_SIZE, FILE_SIZE_THRESHOLD);
return multipartConfigElement;
}
private static final String LOCATION = System.getenv("TEMP").replace('\\', '/') + "/"; // Temporary location where files will be stored
private static final long MAX_FILE_SIZE = 5242880; // 5MB : Max file size.
// Beyond that size spring will throw exception.
private static final long MAX_REQUEST_SIZE = 20971520; // 20MB : Total request size containing Multi part.
private static final int FILE_SIZE_THRESHOLD = 0; // Size threshold after which files will be written to disk
}

Related

No thread-bound request found with Spring when Kafka receive a message

I 'm getting this error from my service
jvm org.hibernate.internal.ExceptionMapperStandardImpl {"#trace_info":"[availability-psql,eba16d49e23479cc,675789f41e0dda5b,eba16d49e23479cc,false]", "#message": "HHH000346: Error during managed flush [Error creating bean with name 'scopedTarget.infoUser': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.]
This is because of I have a bean of scope #ScopeRequest. This problem show up when a new message from kafka is received and I try to update my data base with spring data. If I remove my #Transactional I don't have any problem to save the data.
#KafkaListener(topics = "#{kafkaMastersConfig.topics}", containerFactory = "mastersContainerFactory")
#Transactional
#Authorized
public void consumeWrapperMasterChangeEvent(#Payload String payload,
#Header(KafkaHeaders.RECEIVED_TOPIC) String topic, #Nullable #Header(AUTHORIZATION) String authorization) throws IOException {
try {
log.info("Received change event in masters: '{}'", payload);
RequestAttributes context = RequestContextHolder.currentRequestAttributes();
RequestContextHolder.setRequestAttributes(context);
changeProcessorFactory.getEntityChangeProcessor(getEntityFromTopic(topic)).processChange(payload);
} catch ( Exception e ) {
log.error("Error proccesing message {} ", e.getMessage());
} finally {
RequestContextHolder.resetRequestAttributes();
}
}
And here is the bean:
#RequestScope
#Component
#NoArgsConstructor
#Getter
#Setter
public class InfoUser {
private DecodedJWT jwt;
public String getCurrentUser() {
if (jwt == null) {
return null;
}
return jwt.getSubject();
}
public String getAuthorizationBearer() {
if (jwt == null) {
return null;
}
return jwt.getToken();
}
}
And this class:
public class CustomRequestScopeAttr implements RequestAttributes {
private Map<String, Object> requestAttributeMap = new HashMap<>();
#Override
public Object getAttribute(String name, int scope) {
if (scope == RequestAttributes.SCOPE_REQUEST) {
return this.requestAttributeMap.get(name);
}
return null;
}
#Override
public void setAttribute(String name, Object value, int scope) {
if (scope == RequestAttributes.SCOPE_REQUEST) {
this.requestAttributeMap.put(name, value);
}
}
#Override
public void removeAttribute(String name, int scope) {
if (scope == RequestAttributes.SCOPE_REQUEST) {
this.requestAttributeMap.remove(name);
}
}
#Override
public String[] getAttributeNames(int scope) {
if (scope == RequestAttributes.SCOPE_REQUEST) {
return this.requestAttributeMap.keySet().toArray(new String[0]);
}
return new String[0];
}
#Override
public void registerDestructionCallback(String name, Runnable callback, int scope) {
// Not Supported
}
#Override
public Object resolveReference(String key) {
// Not supported
return null;
}
#Override
public String getSessionId() {
return null;
}
#Override
public Object getSessionMutex() {
return null;
}
}
And futhermore I have an aspect class to save the authorization token:
#Aspect
#Component
#RequiredArgsConstructor
public class AuthorizationAspect {
private final AuthorizationDecoder authorizationDecoder;
private final ApplicationContext applicationContext;
#Around("#annotation(Authorized)")
public Object setInfoUser(ProceedingJoinPoint joinPoint) throws Throwable {
try {
String[] parameterNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
Object[] args = joinPoint.getArgs();
Map<String, Object> arguments = new HashMap<>();
for (int i = 0; i < args.length; i++) {
if (null != args[i]) {
arguments.put(parameterNames[i], args[i]);
}
}
Object authorization = arguments.get("authorization");
RequestContextHolder.setRequestAttributes(new CustomRequestScopeAttr());
InfoUser infoUser = applicationContext.getBean(InfoUser.class);
infoUser.setJwt(authorizationDecoder.decodeToken((String) authorization));
return joinPoint.proceed();
} finally {
RequestContextHolder.resetRequestAttributes();
}
}
And the last class is trying to save de info:
#RequiredArgsConstructor
public class RoomChangeMaster implements ChangeMaster<Room> {
private final TimetableRepository timetableRepository;
private final AvailabilityRepository availabilityRepository;
#Override
public void processChange(Room entity, ActionEnum action) {
if (action == ActionEnum.updated) {
List<Timetable> timetables = (List<Timetable>) timetableRepository.findByRoomId(entity.getId());
Room room = timetables.get(0).getRoom();
room.setDescription(entity.getDescription());
room.setCode(entity.getCode());
timetables.forEach(timetable -> {
timetable.setRoom(room);
timetableRepository.save(timetable);
});
availabilityRepository
.updateAvailabilityRoomByRoomId(room, entity.getId());
} else {
throw new IllegalStateException("Unexpected value: " + action);
}
}
}
I have spent a lot of time finding out the problem, but so far, I was not able to know the problem. Any idea will be appreciate.
Thank you
RequestContextHolder is for Spring-MVC - it is for a Web request only and is populated with information from an HTTP request.
/**
* Holder class to expose the web request in the form of a thread-bound
* {#link RequestAttributes} object. The request will be inherited
* by any child threads spawned by the current thread if the
* {#code inheritable} flag is set to {#code true}.
*
...
There is no equivalent for listener containers (of any type) because there is no "incoming request".
Looks like your hibernate code is tightly tied to the web.
If you are trying to reuse existing code you need to decouple it and use some other technique to pass information between the layers (e.g. a custom equivalent of RequestContextHolder).
Finally, I have solved it changing the hiberante method save by saveAndFlush

Could not read freemarker template

My file is under
src/main/resources/freemarker/email_notification.txt
I am not able to read the freemaker file, that is email_notification.txt, which contain html file.
My Reference is from here: http://websystique.com/spring/spring-4-email-using-velocity-freemaker-template-library/
I have tried the velocity method but there is strikethrough in some of the words, thus i choose freemarker method instead.
#Transactional
#Service("EmailService")
public class EmailService{
#Autowired
JavaMailSender mailSender;
#Autowired
Configuration freemarkerConfiguration;
public void sendEmail(Map<String, Object> params) {
MimeMessagePreparator preparator = getMessagePreparator(params);
try {
mailSender.send(preparator);
System.out.println("Message has been sent.............................");
}
catch (MailException ex) {
System.err.println(ex.getMessage());
}
}
private MimeMessagePreparator getMessagePreparator(final Map<String, Object> params){
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setSubject(params.get("trnmaster").toString());
helper.setFrom("XXXXX#gmail.com");
helper.setTo("XXXXXX#hotmail.com");
String text = geFreeMarkerTemplateContent(params);//Use Freemarker or Velocity
System.out.println("Template content : "+text);
helper.setText(text, true);
}
};
return preparator;
}
public String geFreeMarkerTemplateContent(Map<String, Object> model){
StringBuffer content = new StringBuffer();
try{
content.append(FreeMarkerTemplateUtils.processTemplateIntoString(
freemarkerConfiguration.getTemplate("/email_notification.txt"),model));
return content.toString();
}catch(Exception e){
System.out.println("Exception occured while processing fmtemplate:"+e.getMessage());
}
return "";
}
}
part of the config file
#Bean
public FreeMarkerConfigurationFactoryBean getFreeMarkerConfiguration() {
FreeMarkerConfigurationFactoryBean bean = new FreeMarkerConfigurationFactoryBean();
bean.setTemplateLoaderPath("classpath:/freemarker/");
return bean;
}
Where you configure FreeMarker, you should use: bean.setTemplateLoaderPath("classpath:/freemarker/");
Also that example is quite strange. Why's the file extension txt? It should be ftlh for a HTML template (was ftl in older projects). Also I would definitely overwrite FreeMarkerConfigurationFactoryBean.postProcessConfiguration and do the recommended setup according to https://freemarker.apache.org/docs/pgui_quickstart_createconfiguration.html, except that you must not call setDirectoryForTemplateLoading, and maybe setDefaultEncoding is already set by Spring as well. It's important to ensure that you get automatic HTML escaping (incompatibleImprovements set to 2.3.24 or higher and the ftlh file extension does that).

Type mismatch: cannot convert from String to ListenableFuture<String>

I'm trying to implementing non-blocking call. in spring 4, But unfortunately it's throwing the below error.
Type mismatch: cannot convert from String to ListenableFuture
and also same error can not able convert from Map to ListenableFuture>.
My Method call stack is as below.
ListenableFuture<Map<String,String>> unusedQuota = doLogin(userIdentity,request,"0");
doLogin login simply return Map
is there any converter required?
what changes would be required ?
Thanks.
public class MyController {
final DeferredResult<Map<String,String>> deferredResult = new DeferredResult<Map<String,String>>(5000l);
private final Logger log = LoggerFactory.getLogger(MyController.class);
#Inject
RestTemplate restTemplate;
#RequestMapping(value = "/loginservice", method = RequestMethod.GET)
#Timed
public DeferredResult<Map<String,String>> loginRequestService(#RequestParam String userIdentity,HttpServletRequest request) throws Exception {
deferredResult.onTimeout(new Runnable() {
#Override
public void run() { // Retry on timeout
deferredResult.setErrorResult(ResponseEntity.status(HttpStatus.REQUEST_TIMEOUT).body("Request timeout occurred."));
}
});
#SuppressWarnings("unchecked")
ListenableFuture<Map<String,String>> unusedQuota = doLogin(userIdentity,request);
unusedQuota.addCallback(new ListenableFutureCallback<Map<String,String>>() {
#SuppressWarnings("unchecked")
#Override
public void onSuccess(Map<String, String> result) {
// TODO Auto-generated method stub
deferredResult.setResult((Map<String, String>) ResponseEntity.ok(result));
}
#Override
public void onFailure(Throwable t) {
// TODO Auto-generated method stub
deferredResult.setErrorResult(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(t));
}
});
return deferredResult;
}
private Map<String,String> doLogin(String userIdentity,HttpServletRequest request) throws Exception{
Map<String,String> unusedQuota=new HashMap<String,String>();
unusedQuota.put("quota", "100");
return unusedQuota;
}
}
}
You are NOT passing the Map object when there is an exception which is causing the issue, so your controller method needs to be changed as shown below, also move deferredResult object inside the Controller method as you should share the same instance of deferredResult for different user request.
public class MyController {
#Autowired
private TaskExecutor asyncTaskExecutor;
#RequestMapping(value = "/loginservice", method = RequestMethod.GET)
#Timed
public DeferredResult<Map<String,String>> loginRequestService(#RequestParam String userIdentity,HttpServletRequest request) throws Exception {
final DeferredResult<Map<String,String>> deferredResult = new DeferredResult<Map<String,String>>(5000l);
deferredResult.onTimeout(new Runnable() {
#Override
public void run() { // Retry on timeout
Map<String, String> map = new HashMap<>();
//Populate map object with error details with Request timeout occurred.
deferredResult.setErrorResult(new ResponseEntity
<Map<String, String>>(map, null,
HttpStatus.REQUEST_TIMEOUT));
}
});
ListenableFuture<String> task = asyncTaskExecutor.submitListenable(new Callable<String>(){
#Override
public Map<String,String> call() throws Exception {
return doLogin(userIdentity,request);
}
});
unusedQuota.addCallback(new ListenableFutureCallback<Map<String,String>>() {
#SuppressWarnings("unchecked")
#Override
public void onSuccess(Map<String, String> result) {
// TODO Auto-generated method stub
deferredResult.setResult((Map<String, String>) ResponseEntity.ok(result));
}
#Override
public void onFailure(Throwable t) {
Map<String, String> map = new HashMap<>();
//Populate map object with error details
deferredResult.setErrorResult(new ResponseEntity<Map<String, String>>(
map, null, HttpStatus.INTERNAL_SERVER_ERROR));
}
});
return deferredResult;
}
}
Also, you need to ensure that you are configuring the ThreadPoolTaskExecutor as explained in the example here.

spring Java config for excel view resolver

I have a spring java config based web app with (jsp) view resolver.
Now i want to show a excel sheet with some data when user clicks on excel icon in app.
All over internet i only found xml based spring config for excel view with which i am not familiar with.
I decoded to some extent and came pretty close to get my task done. Below is what i got.
I have similar controller and Homepage following the below link:
http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch17s06.html
Controlle Code:
#Controller
public class ExcelController extends AbstractController {
#Override
#RequestMapping(value = "/Excel", method = RequestMethod.POST)
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
BufferedReader in = null;
try {
URL oracle = new URL("example.com");
URLConnection yc =null;
yc = oracle.openConnection();
in = new BufferedReader(
new InputStreamReader(
yc.getInputStream()));
}
catch(Exception e){
System.err.println(e);
}
Map map = new HashMap();
map.put("input", in);
return new ModelAndView("xl", map);
}
}
View Code:
public class ExcelReportView extends AbstractExcelView{
#Override
protected void buildExcelDocument(Map model, HSSFWorkbook workbook,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
HSSFSheet sheet;
HSSFRow row;
HSSFCell cell;
try {
BufferedReader in = (BufferedReader) model.get("input");
sheet=workbook.createSheet("spring");
String inputLine;
int rowNum =0;
while ((inputLine = in.readLine()) != null) {
row = sheet.createRow(rowNum++);
String[] coloumns = inputLine.split("\t");
int cellNum =0;
for(String coloumn: coloumns){
cell = row.createCell(cellNum++);
cell.setCellValue(coloumn);
}
System.out.println(inputLine);
}
in.close();
System.out.println("Excel written successfully..");
} catch (IOException e) {
e.printStackTrace();
}
}
}
view.properties
xl.class=package.ExcelReportView
WebAppConfig.java
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "package")
public class WebAppContextConfig extends WebMvcConfigurerAdapter {
// Resolve logical view names to .jsp resources in /WEB-INF/views directory
#Bean
public InternalResourceViewResolver configureInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/scripts/**").addResourceLocations(
"/scripts/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/img/**").addResourceLocations("/img/");
}
}
Front end Code:
function AjaxCallForExcel(){
$.ajax({
type: 'POST',
url: location.href + '/Excel',
data: ({name:name })
});
}
Below is what i see in logs:
DispatcherServlet with name 'appServlet' processing POST request for [/App/Excel]
Looking up handler method for path /App/Excel
Returning handler method [protected org.springframework.web.servlet.ModelAndView package.ExcelController.handleRequestInternal(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception]
Returning cached instance of singleton bean 'excelController'
Invoking afterPropertiesSet() on bean with name 'xl'
Rendering view [org.springframework.web.servlet.view.JstlView: name 'xl'; URL [**/WEB-INF/jsp/xl.jsp**]] in DispatcherServlet with name 'appServlet'
Added model object 'org.springframework.validation.BindingResult.input' of type [org.springframework.validation.BeanPropertyBindingResult] to request in view with name 'xl'
Added model object 'input' of type [java.io.BufferedReader] to request in view with name 'xl'
Forwarding to resource [/WEB-INF/jsp/xl.jsp] in InternalResourceView 'xl'
Successfully completed request
I dont know how to avoid it from forwarding it to xl.jsp. I am sure view resolver is making it into jsp view. Can someone point how can i fix it.
EDIT
I saw this xml equivalent config online. Not sure how to make it java config:
<bean id="excelViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver">
<property name="order" value="1"/>
<property name="location" value="/WEB-INF/views.xml"/>
</bean>
i tried converting it the below way:
#Bean
public XmlViewResolver configureXmlViewResolver(){
XmlViewResolver resolver = new XmlViewResolver();
resolver.setOrder(1);
resolver.setLocation(**WHAT SHOULD BE HERE**);
}
I dont know what to put in location. I cant give string. i dont have views.xml as i am use java configs
Edit(Here is my code after making changes as you said)
public class ExcelReportView extends AbstractExcelView{
BufferedReader in;
ExcelReportView(BufferedReader in){
this.in = in;
}
#Override
protected void buildExcelDocument(Map model, HSSFWorkbook workbook,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
HSSFSheet sheet;
HSSFRow row;
HSSFCell cell;
response.setHeader("Content-Type", "application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=MyExcelSpreadsheet.xls");
try {
//BufferedReader in = (BufferedReader) model.get("input");
sheet=workbook.createSheet("spring");
String inputLine;
int rowNum =0;
while ((inputLine = in.readLine()) != null) {
row = sheet.createRow(rowNum++);
String[] coloumns = inputLine.split("\t");
int cellNum =0;
for(String coloumn: coloumns){
cell = row.createCell(cellNum++);
cell.setCellValue(coloumn);
}
System.out.println(inputLine);
}
in.close();
System.out.println("Excel written successfully..");
} catch (IOException e) {
e.printStackTrace();
}
OutputStream outStream = null;
try {
outStream = response.getOutputStream();
workbook.write(outStream);
outStream.flush();
} finally {
outStream.close();
}
}
}
Controller Code:
#Controller
public class ExcelController {
#RequestMapping(value = "/Excel", method = RequestMethod.POST)
protected ModelAndView generateCSV(HttpServletRequest request,
HttpServletResponse response) throws Exception {
BufferedReader in = null;
try {
URL oracle = new URL("http://service.com");
URLConnection yc =null;
yc = oracle.openConnection();
in = new BufferedReader(
new InputStreamReader(
yc.getInputStream()));
}
catch(Exception e){
System.err.println(e);
}
ModelAndView mav = new ModelAndView();
mav.setView(new ExcelReportView( in));
return mav;
}
}
Log output:
DispatcherServlet with name 'appServlet' processing POST request for [/App/Excel]
Looking up handler method for path /App/Excel
Returning handler method [protected org.springframework.web.servlet.ModelAndView com.package.ExcelController.generateCSV(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception]
Returning cached instance of singleton bean 'excelController'
Rendering view [com.package.controllers.ExcelReportView: unnamed] in DispatcherServlet with name 'appServlet'
Created Excel Workbook from scratch
Title Id required
Excel written successfully..
Successfully completed request
EDIT:
Response Header:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Pragma: private
Cache-Control: private, must-revalidate
Content-Disposition: attachment; filename=MyExcelSpreadsheet.xls
Content-Type: application/octet-stream;charset=ISO-8859-1
Content-Language: en-US
Transfer-Encoding: chunked
Date: Tue, 12 Mar 2013 16:36:52 GMT
You can return a ModelAndView from your controller method, setting the View to an instance of AbstractExcelView. Then you don't need to mess with your XML at all.
Edit: Add some additional info:
I have done the custom View approach many times to handle CSV downloads.
First, you need to create an instantiation of the AbstractExcelView. You would do so by overwriting the buildExcelDeocument() method. You will need the POI libraries, as I believe it is required. For example:
#Override
public void buildExcelDocument(Map<String, Object> model, HSSFWorkbook workbook,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
// Set the headers
response.setHeader("Content-Type", "application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=MyExcelSpreadsheet.xls");
// Here is where you will want to put the code to build the Excel spreadsheet
OutputStream outStream = null;
try {
outStream = response.getOutputStream();
workbook.write(outStream);
outStream.flush();
} finally {
outStream.close();
}
}
Next you need to modify the Controller method
#RequestMapping(params = "actionMethod="+Constants.ACTION_METHOD_REPORT)
public ModelAndView generateCSV(
#ModelAttribute(Constants.REPORT_FORMBEAN_MODEL_ATTRIBUTE) FormBean formBean,
ModelAndView mav,
HttpServletRequest request,
HttpServletResponse response) {
mav.setView(new MyExcelView( /* modify your constructor to pass in your data so the view can build the output */ ));
return mav;
}
There is no need to edit your context XML, modify how your beans are wired together, create any services, or anything. Simply create an instance of your custom View, pass in whatever you need to in order to build the spreadsheet, then set the view on the ModelAndView. Simple as that.
EDIT - You need to do this...
You need to change your AJAX call so that you can tell if its done or had an error. You are flying blind right now:
function AjaxCallForExcel(){
$.ajax({
type: 'POST',
url: location.href + '/Excel',
data: ({name:name }),
complete: function(jqXHR,textStatus ) {
alert("Complete: "+textStatus );
},
error: function(jqXHR,textStatus,errorThrown ) {
alert("Status: "+textStatus+"\nerror: "+errorThrown );
}
});
}

spring-mvc + jpa: data binding

I have simple application which manages football teams and matches. I am using JPA, in the form editMatch.jsp i have property team_1, team_2 (instance of class Team) for choosing the team from the list. The problem is when editing match, the team_1 and team_2 dont select in the list, and after submitting the error message is: Property team_1 threw exception; nested exception is java.lang.NullPointerException. In the controller I am binding team_1, team_2 and I suppose that the error is somewhere between binding and initialization of the form.
editMatch.jsp
<form:select path="team_1">
<form:options items="${teamList}" itemLabel="name" itemValue="id"/>
</form:select>
EditMatchController
public class EditMatchController extends SimpleFormController {
private MatchManager manager;
public EditMatchController() {}
#Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
Match match = (Match)binder.getTarget();
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try{
binder.registerCustomEditor(Date.class, "datum", new CustomDateEditor(sdf, false));
} catch(Exception e){}
binder.registerCustomEditor(Team.class, new TeamPropertyEditor());
binder.registerCustomEditor(Team.class, new TeamPropertyEditor());
}
#Override
protected Map referenceData(HttpServletRequest request) throws Exception {
Map<Object, Object> dataMap = new HashMap<Object, Object>();
dataMap.put("teamList", manager.getTeams());
return dataMap;
}
#Override
protected Object formBackingObject(HttpServletRequest request) throws Exception {
int idMatch = Integer.parseInt(request.getParameter("id"));
Match match_d = manager.getMatchById(idMatch);
if (match_d == null) {
throw new GenericException("Neplatný záznam.");
}
return match_d;
}
#Override
protected ModelAndView onSubmit(
HttpServletRequest request,
HttpServletResponse response,
Object command,
BindException errors) throws Exception {
Match match = (Match)command;
manager.updateMatch(match);
RedirectView redirect = new RedirectView(getSuccessView());
return new ModelAndView(redirect).addObject("message", match);
}
public void setManager(MatchManager manager) {
this.manager = manager;
}
}
TeamPropertyEditor
public class TeamPropertyEditor extends PropertyEditorSupport {
private MatchManager manager;
public void setManager(MatchManager manager) {
this.manager = manager;
}
#Override
public void setAsText(String text) throws IllegalArgumentException {
if (text != null && text.length() > 0) {
try {
Team team = this.manager.getTeamById(new Integer(text));
super.setValue(team);
} catch (NumberFormatException ex) {
throw new IllegalArgumentException();
}
} else {
super.setValue(null);
}
}
#Override
public String getAsText() {
Team team = (Team) super.getValue();
return (team != null ? (team.getId()+"").toString(): "");
}
}
edit:
errors.getFieldError("team_1"):
Field error in object 'match' on field 'team_1': rejected value [6]; codes [methodInvocation.match.team_1,methodInvocation.team_1,methodInvocation.model.Team,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [match.team_1,team_1]; arguments []; default message [team_1]]; default message [Property 'team_1' threw exception; nested exception is java.lang.NullPointerException]
You instantiate TeamPropertyEditor but don't call setManager() on it, so its manager field is null, therefore you get NPE when trying to call manager.getTeamById(...).

Resources