Asked on this Liferay Forum post
I am trying to make an AJAX request from my Lifery portlet utilizing <portlet:resourceURL>.
index.jsp
<portlet:resourceURL var="search" id="recordId"></portlet:resourceURL>
CLICK ME
<script>
var id = 100;
function ajaxCall(ajaxUrl){
$.ajax({
url : ajaxUrl,
data : {
id: id
},
type: 'GET',
dataType : "json",
success : function(data) {
// do stuff on success
},
error: function () {
//do stuff on error
console.log('Error Occurred');
}
});
}
</script>
And my #Controller
#Controller
#PropertySource("classpath:application.properties")
#RequestMapping(value = "VIEW")
public class SearchController {
#ActionMapping
public void handleActionRequest(ActionRequest request, ActionResponse response)throws Exception {
System.out.print("In the Action Mapping Handler");
return;
}
#RenderMapping
public ModelAndView handleRenderRequest(RenderRequest request, RenderResponse response, ModelMap model) {
return new ModelAndView("index", model);
}
#ResourceMapping(value = "search")
#ResponseBody
public void getPlan(ResourceRequest request, ResourceResponse response) throws PortalException, SystemException, IOException {
System.out.println("In the search Controller");
}
}
However I am getting the error and am not sure why
org.springframework.web.portlet.NoHandlerFoundException: No handler found for portlet request: mode 'view', phase 'RESOURCE_PHASE', parameters map[[empty]]
The Request URL:
http://localhost:8090/portal/web/mySite/home?p_p_id=MyApp_WAR_MyApp&p_p_lifecycle=2&p_p_state=normal&p_p_mode=view&p_p_resource_id=recordId&p_p_cacheability=cacheLevelPage&p_p_col_id=column-1&p_p_col_count=1&id=100
Any ideas?
#ResourceMapping(value="recordId") would work as mentioned by Pankaj.
Related
I am trying to check my #RestController with Postman but when I enter localhost:8081/rest/teachers/remove/2 I gain this error
My RestController :
#RestController
#RequestMapping("/rest/teachers")
public class TeacherRestController {
private static final String TEACHER_MODEL = "teacher";
#Autowired
TeacherService teacherService;
#DeleteMapping("/remove/{id}")
public ResponseEntity<HttpStatus> deleteTeacher(#PathVariable("id") long id) {
try {
teacherService.removeTeacher(teacherService.getTeacherById((int) id));
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
It is my foolish mistake.
I sent "GET" request on the Postman.
When I switched it to "Delete", it worked.
BackEnd is Spring, I'v configured CORS like this
#SpringBootApplication
public class App {
public static void main(String args[]){
SpringApplication.run(App.class, args);
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*");
}
};
}
}
Now I got following code in Controller
#PostMapping("/add")
public ProductDto addProduct(#Valid #RequestBody ProductDto productDto){
return productService.addProduct(productDto);
}
#RequestMapping(path="/remove/{id}", method=RequestMethod.DELETE)
#ResponseBody
public String removeProduct(#PathVariable Long id) {
return productService.removeProduct(id);
}
And from Angular 6 FrontEnd I'm calling those 2 endpoints
let httpHeaders = new HttpHeaders({
'Content-Type' : 'application/json',
});
let options = {
headers: httpHeaders
};
addProduct() {
const product = new Product();
product.name = this.productNameValue;
product.categoryName = this.categoryValue;
product.kcal = this.caloriesValue;
product.protein = this.proteinValue;
product.fat = this.fatValue;
product.carb = this.carbsValue;
this.http.post('http://localhost:8080/product/add', JSON.stringify(product), options).subscribe(data => this.populateProductTable());
}
removeProduct(x: any) {
const url = 'http://localhost:8080/product/remove/' + x.id;
this.http.delete(url, options).subscribe(data => console.log(data));
}
First one (and similar GET method) works fine, when I try to use DELETE, I got
Failed to load http://localhost:8080/product/remove/2: Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:4200' is therefore not allowed
access.
You need to add DELETE http-verb
For Spring Web MVC
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
}
For Spring Boot:
#Configuration
public class MyConfiguration {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
};
}
}
To know how CORS works with spring, refer:
https://spring.io/blog/2015/06/08/cors-support-in-spring-framework#javaconfig
Spring security CORS Filter
was trying to implement a simple demo of jstree using jstree json and servlet but my ajax call to servlet is not working must be a minor error but still not working please guide me
on this would very grateful.
1) The jsp page called the jsp tree initialization on page load
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Chetan Jtree</title>
<link rel="stylesheet"
href="${pageContext.request.contextPath}/themes/default/style.min.css" />
<script
src="${pageContext.request.contextPath}/jquery-1.9.1.js"></script>
<script src="${pageContext.request.contextPath}/jstree.min.js"></script>
<script src="${pageContext.request.contextPath}/jtreedemo.js"></script>
</head>
<body onload="initTrees()">
<div id="jstreeloaddiv"></div>
</body>
2) The js file where the inittree function is written jtreedemo
function initTrees() {
$("#jstreeloaddiv").jstree({
"plugins" : [ "themes", "json_data", "ui" ],
"json_data" : {
"ajax" : {
"type" : "POST",
"url" : "/JSTreeDemoServlet",
"data" : function(n) {
return {
"criteria" : "get_children"
};
},
"success" : function(new_data) {
alert(new_data);
return new_data;
},
"error" : function(xhr, textStatus, errorThrown) {
alert('request failed' + textStatus);
},
"fail" : function(jqXHR, textStatus) {
alert("Request failed: " + textStatus);
}
}
}
});
}
3) The servlet from where the json data is being send and to which ajax call fails.
#WebServlet("/JSTreeDemoServlet")
public class JSTreeDemoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public JSTreeDemoServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println(request.getParameter("criteria"));
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
JSONArray jsonarr = new JSONArray();
JSONArray jsonarrattr = new JSONArray();
PrintWriter out= response.getWriter();
System.out.println(request.getParameter("criteria"));
for(int i =0;i<5;i++){
JSONObject jsonobj = new JSONObject();
try {
jsonarrattr = new JSONArray();
jsonobj.put("data", "Bmw"+i);
jsonarr.put(jsonobj);
jsonobj = new JSONObject();
jsonobj.put("id", i);
jsonobj.put("name", "chetan");
jsonarrattr.put(jsonobj);
jsonobj = new JSONObject();
jsonobj.put("attr", jsonarrattr);
jsonarr.put(jsonobj);
jsonobj = new JSONObject();
jsonobj.put("state", "closed");
jsonarr.put(jsonobj);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
out.print(jsonarr);
}
}
i think you have to use:
$(document).ready(function(){
initTrees();
});
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 );
}
});
}
I want to display servlet response in my JSP page (as a hyperlink) through an ajax call. Can anyone please tell me how I could display the content in my jsp page? I am also not too sure if I am doing it the right way. There could be some errors in either my servlet class or Ajax.js. I'm still in learning phase. Here is my code snippet:
JSP page
<script type="text/javascript"> var AJAX_SERVLET="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/ajaxServlet";
</script>
<label for="push">Push to start</label>
<button dojoType="dijit.form.Button" style="width: 4em" type="button" name="submitButton" value="Submit" onclick="ajaxFunction()"></button>
Ajax.js
function ajaxFunction() {
if (xmlhttp) {
xmlhttp.open("GET", AJAX_SERVLET, true); //AJAX_SERVLET has the servlet path
xmlhttp.onreadystatechange = handleServerResponse;
xmlhttp.setRequestHeader('Content-Type',
'application/x-www-form-urlencoded');
xmlhttp.send(null);
}
}
function handleServerResponse() {
if (xmlhttp.readyState == 4) {
//alert(xmlhttp.status);
if (xmlhttp.status == 200) {
var resultContent =httpRequest.getResponseHeader("Content-Type");
} else {
alert("Error during AJAX call. Please try again");
}
}
Getters/Setters
public class SearchResponse {
private String productNumber;
private String productType;
private String funcDesignation;}
Servlet Class
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
List result = new ArrayList();
result.add(new SearchResponse("001", "User Manual", "Operator"));
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(new Gson().toJson(result));
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
doPost(request, response);
}