JSP code --- I have used Angular js in scripting. The issue is that the form Data is not being sent to the resource method in portlet class. Also when I log the form data in console it displays empty. It takes up JSON data and append into form data. the json value is passed as transaction data { 1: "1", purchaseRegisterId: 33411, undefined: "book3.jpg" } and documentId is passed as documentId :: documents33411. these data is taken from the console log.
$scope.savePurchaseRegisterEntry=function(documentId, json){
console.log("documentId :: "+documentId);
//console.log("json");
console.log(json);
var fd = new FormData();
fd.append('auditDetailesId',$scope.auditDetailesId);
console.log(fd);
var documentcollection=[];
for(var key in json){
fd.append(key,json[key]);
if("purchaseRegisterId"!=key && key!=='undefined'){
documentcollection.push(key);
}
}
$.each( $("#"+documentId), function( input_key, input_value ) {
$.each( input_value.files, function( file_key, file_value ) {
fd.append('myFiles', file_value);
});
});
fd.append("documentCollectionIds",documentcollection.join(','));
console.log("fd");
console.log(fd);
console.log("documentcollectionids :: "+documentcollection.join(','))
//return false;
$http({
method:'POST',
url:'<%=savePurchaseRegisterEntry%>',
type:"json",
data:fd,
headers: {'Content-Type': undefined},
transformRequest:angular.identity
}).success(function(response){
console.log(response);
var response=angular.fromJson(response.selectedTransactionList);
$scope.dataList=angular.fromJson(response.data);
$scope.ariaValuenow =response.currentCount;
$scope.ariaValuemin=0;
$scope.ariaValueMax=response.data[0]['maxInputDocCount']* response.total;
$scope.percentageComplete=(($scope.ariaValuenow - $scope.ariaValuemin) * 100) / ($scope.ariaValueMax - $scope.ariaValuemin);
if($scope.percentageComplete==100){
$scope.saveStatus();
$scope.readyForAudit=true;
}else{
$scope.readyForAudit=false;
}
});
}
Resurces Method --- the data is being fetched here to store the values into database table.
public void savePurchaseRegisterEntry(ResourceRequest req,
ResourceResponse res) throws SystemException, IOException {
_log.info("i am in savePurchaseRegisterEntry!!!");
ThemeDisplay themeDisplay = (ThemeDisplay) req
.getAttribute(WebKeys.THEME_DISPLAY);
_log.info(" ----- " + ParamUtil.getString(req, "purchaseRegisterId"));
_log.info(" ----- " + ParamUtil.getLong(req, "purchaseRegisterId"));
String documentCollectionIds=ParamUtil.getString(req, "documentCollectionIds");
String[] documentCollectionIdArray=documentCollectionIds.split(",");
MultiDocumentUploadUtil.createFolder(req, themeDisplay ,ParamUtil.getLong(req, "purchaseRegisterId") , "purchaseRegisterId");
String fileIds=MultiDocumentUploadUtil.fileUpload(themeDisplay, req);
_log.info("fileIds : "+fileIds);
long purchaseRegisterId =ParamUtil.getLong(req, "purchaseRegisterId");
for(String s : documentCollectionIdArray){
System.out.println("s is "+Long.parseLong(s));
_log.info(Long.parseLong(s)+"long sssss "+ s+" s :: "+ParamUtil.getLong(req, s));
_log.info(Long.valueOf(s)+"long sssss "+ s+" s :: "+ParamUtil.getLong(req, s));
AuditDocumentCollection adc= AuditDocumentCollectionLocalServiceUtil.fetchByPurchaseRegisterIdAnddocumentCollectionId(purchaseRegisterId, Long.valueOf(s));
AuditDocumentCollection adc1=adc;
if(adc==null){
adc=AuditDocumentCollectionLocalServiceUtil.createAuditDocumentCollection(CounterLocalServiceUtil.increment());
}
adc.setDocumentCollectionId(Long.valueOf(s));
adc.setPurchaseRegisterId(purchaseRegisterId);
adc.setValue(ParamUtil.getLong(req, s));
if(adc1==null){
adc.setCreateDate(new Date());
adc.setCreatedBy(themeDisplay.getUserId());
adc.setModifiedBy(themeDisplay.getUserId());
adc.setModifiedDate(new Date());
AuditDocumentCollectionLocalServiceUtil.addAuditDocumentCollection(adc);
}else{
adc.setModifiedBy(themeDisplay.getUserId());
adc.setModifiedDate(new Date());
AuditDocumentCollectionLocalServiceUtil.updateAuditDocumentCollection(adc);
}
}
PurchaseRegister purchaseRegister=PurchaseRegisterLocalServiceUtil.fetchPurchaseRegister(purchaseRegisterId);
if(!fileIds.isEmpty()){
purchaseRegister.setDocumentIds(fileIds);
}
PurchaseRegisterLocalServiceUtil.updatePurchaseRegister(purchaseRegister);
JSONObject jsonobject = JSONFactoryUtil.createJSONObject();
long auditDetailesId=ParamUtil.getLong(req, "auditDetailesId");
jsonobject.put("selectedTransactionList",CommonUtil.getAuditProcessInfo( auditDetailesId));
PrintWriter out = res.getWriter();
out.write(jsonobject.toString());
out.flush();
out.close();
}
I suppose the data present in form data is being sent to resource method. it is not taking documentCollectionIds and its empty. The error I get is this,
[http-bio-3030-exec-10][PurchaseRegisterPortlet:644] i am in savePurchaseRegisterEntry!!!
05:58:34,050 INFO [http-bio-3030-exec-10][PurchaseRegisterPortlet:648] -----
05:58:34,050 INFO [http-bio-3030-exec-10][PurchaseRegisterPortlet:649] ----- 0
Folder is already Exist
fileEntryList.toArray().toString() :: 34529
05:58:34,255 INFO [http-bio-3030-exec-10][PurchaseRegisterPortlet:657]fileIds : 34529
Exception in thread "liferay/document_library_image_processor-3"05:58:34,256 ERROR [DispatcherPortlet:559] Could not complete request
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:453)
at java.lang.Long.parseLong(Long.java:483)
at com.auditcompliance.purchaseregister.controller.PurchaseRegisterPortlet.savePurchaseRegisterEntry(PurchaseRegisterPortlet.java:660)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
check your file first the typscript file of your component if you give
it exactly the type Number, then your service
Or if it's through the html file of your component that you give it
the right type in parameter
For me it was in the html file that I gave him another type
different from number
Related
EDIT :
If I hit directly the endpoint from the browser, the file is dowloaded correctly.
So I guess the problem is in the front and the way to create and save the file with the data received.
I have a java/spring boot application where I want to build an API endpoint that creates and returns a downloadable excel file. Here is my controller endpoint:
#GetMapping(path = "/informe/{informeDTO}")
public ResponseEntity<InputStreamResource> generarInforme(#PathVariable(value = "informeDTO") String informeDTOString) throws JsonParseException, JsonMappingException, IOException {
final InformeDTO informeDTO =
new ObjectMapper().readValue(informeDTOString, InformeDTO.class);
List<InformeDTO> listDatosinformeDTO = utilsService.getDatosInformeDTO(informeDTO);
for (InformeDTO informeDTO2 : listDatosinformeDTO) {
logger.debug(informeDTO2);
}
ByteArrayInputStream in = createReport(listDatosinformeDTO);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment; filename=IOPreport.xlsx");
return ResponseEntity.ok().headers(headers)
.contentType(
MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
.body(new InputStreamResource(in));
}
This is the angular controller :
function generarInformeIOP(){
InformesService.generarInformeIOP($scope.informeView.sociedad, $scope.informeView.area, $scope.informeView.epigrafe,
$scope.informeView.cuenta, $scope.informeView.status, $scope.informeView.organizationalUnit,
$scope.informeView.societyGL, $scope.informeView.calculationType, $scope.informeView.provincia, $scope.informeView.financialSegment,
$scope.informeView.loadDateFrom, $scope.informeView.loadDateTo, $scope.informeView.incomeDateFrom, $scope.informeView.incomeDateTo)
.then(
function(response)
{
var blob = new Blob([response.data], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"
});
saveAs(blob, "IOPreport.xlsx");
$scope.informeFunctionality.errorMessage = '';
},
function(errResponse)
{
console.log("ERROR: " + errResponse.data);
$scope.informeFunctionality.errorMessage = "Ha ocurrido un error inesperado: " + errResponse.data.error +
": " + errResponse.data.message;
}
)
}
And the service :
....
$http.get(urls.SERVICE_API + "informe/"+ angular.toJson(informeDTO)).then(
function(response) {
console.log("GenerarInformeIOP - success");
deferred.resolve(response);
}, function(errResponse) {
console.log("GenerarInformeIOP - error");
deferred.reject(errResponse);
});
...
The generation is successfull, the file is downloaded but I think it is corrupted because Excel can't open it.
Are there anything wrong?
EDIT (adding createReport) :
private ByteArrayInputStream createReport(List<InformeDTO> datosInforme) {
ByteArrayInputStream result =null;
try (Workbook workbook = new XSSFWorkbook(); ByteArrayOutputStream out = new ByteArrayOutputStream();) {
Set<String> columns = new LinkedHashSet<String>();
// Coumnas fijas
columns.add("Cuenta");
columns.add("Epigrafe");
columns.add("Descripcion");
columns.add("Total_Importe");
// Columnas dinamicas
/*
* Tedremos que recorrer todas las filas puesto que no sabremos si una traera
* menos periodos que otra de esta manera obtendremos todos los periodos
*/
for (InformeDTO informeDTO : datosInforme) {
for (Map.Entry<String, Double> entry : informeDTO.getTotalByPeriodoContable().entrySet()) {
columns.add(entry.getKey());
}
}
/*
* CreationHelper helps us create instances for various things like DataFormat,
* Hyperlink, RichTextString etc in a format (HSSF, XSSF) independent way
*/
// CreationHelper createHelper = workbook.getCreationHelper();
// Create a Sheet
Sheet sheet = workbook.createSheet("IOPReport");
// Create a Font for styling header cells
Font headerFont = workbook.createFont();
headerFont.setBold(true);
headerFont.setFontHeightInPoints((short) 14);
headerFont.setColor(IndexedColors.RED.getIndex());
// Create a CellStyle with the font
CellStyle headerCellStyle = workbook.createCellStyle();
headerCellStyle.setFont(headerFont);
// Create a Row
Row headerRow = sheet.createRow(0);
// Creating cells
int i = 0;
for (String value : columns) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(value);
cell.setCellStyle(headerCellStyle);
i++;
}
// Create Other rows and cells with employees data
int rowNum = 1;
int cellDynamicNum = 0;
for (InformeDTO informeDTO : datosInforme) {
Row row = sheet.createRow(rowNum++);
row.createCell(0).setCellValue(informeDTO.getCuenta());
row.createCell(1).setCellValue(informeDTO.getEpigrafe());
row.createCell(2).setCellValue(informeDTO.getDescripcion_epigrafe());
row.createCell(3).setCellValue("No Data");
cellDynamicNum = 4;
for (Map.Entry<String, Double> entry : informeDTO.getTotalByPeriodoContable().entrySet()) {
row.createCell(cellDynamicNum).setCellValue(entry.getValue());
cellDynamicNum++;
}
}
// Resize all columns to fit the content size
for (i = 0; i < columns.size(); i++) {
sheet.autoSizeColumn(i);
}
// Write the output to a file
workbook.write(out);
result = new ByteArrayInputStream(out.toByteArray());
out.close();
workbook.close();
} catch (Exception e) {
logger.debug("Excepcion en la creacion del report " + e);
}
return result;
}
Regards
When building the output here:
result = new ByteArrayInputStream(out.toByteArray());
The workbook is not saved into out until it is closed. So you need to change the order to:
workbook.close()
result = new ByteArrayInputStream(out.toByteArray());
Closing a ByteArrayOutputStream is not necessary but it's fine if you leave it.
I'm not sure why ResponseEntity<InputStreamResource> is used. I've another working solution which use byte-array ResponseEntity<byte[]>. Some of the code snippet are attached below:
After creating the workbook, write it to outputstream:
private final MediaType mediaType = MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
...
...
// at the end
ByteArrayOutputStream stream = new ByteArrayOutputStream();
workbook.write(stream);
return getDownload(stream.toByteArray(), filename, mediaType);
....
Download method:
public static ResponseEntity<byte[]> getDownload(byte[] content, String filename, MediaType mediaType) {
HttpHeaders headers = new HttpHeaders();
headers.setContentLength(content.length);
headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename);
headers.set(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION);
headers.setContentType(mediaType);
return new ResponseEntity<>(content, headers, HttpStatus.OK);
}
Let me know if this works.
I resolved it adding the reponse type in the front call:
var config = { responseType: 'blob' };
$http.get(urls.SERVICE_API + "informe/"+ angular.toJson(informeDTO), config).then(
....
)
I wrote:
private RequestBuilder getPostRequest(String api) {
return Rest.post(url + api)
.jsonContent()
.header("wsc-access-key", WowzaAccount.getAccessKey())
.header("wsc-api-key", WowzaAccount.getRestKey());
}
getPostRequest("live_streams").body(json).fetchAsJsonMap(new OnComplete<Response<Map>>() {
#Override
public void completed(Response<Map> v) {
if (v.getResponseCode() == 201) {
// success
Map<String, Object> response = v.getResponseData();
name = (String) response.get("name");
id = (String) response.get("id");
connection_code = (String) response.get("connection_code");
Log.p("WowzaLiveStream -> (Code 201) Successfully created live stream with name " + name, Log.DEBUG);
onComplete.completed(instance);
} else if (v.getResponseCode() == 401) {
Log.p("WowzaLiveStream -> (Code 401) Unauthorized, failed to create live stream with name " + params.name.get(), Log.DEBUG);
onFail.run();
} else if (v.getResponseCode() == 422) {
Log.p("WowzaLiveStream -> (Code 422) Unprocessable Entity, failed to create live stream with name " + params.name.get(), Log.DEBUG);
onFail.run();
} else {
Log.p("WowzaLiveStream -> Unknow response with code " + v.getResponseCode() + ", failed to create live stream with name " + params.name.get(), Log.DEBUG);
onFail.run();
}
}
});
The problem is that when I get a 422 response code my onFail callback is not called. Instead a Dialog appears. I suppose that this dialog is invoked by the default addNetworkErrorListener code in the init(). However... I cannot (and I don't want to) disable the default addNetworkErrorListener code, because I'm writing a new CN1Lib. Instead I need that in this case, and only in this case, the network error listener should not be invoked and instead the failure callback that I wrote should be run.
It's more appropriate, in this case, to call the network error listener only if the Internet connection is lost.
Thank you
You need to explicitly catch the error code callback as the callback might have a different format than the main JSON:
private RequestBuilder getPostRequest(String api) {
return Rest.post(url + api)
.jsonContent()
.header("wsc-access-key", WowzaAccount.getAccessKey())
.header("wsc-api-key", WowzaAccount.getRestKey())
.onErrorCodeJSON(map -> {
// process error response
});
}
I GET NullPointerException with status code : 400
I am pushing data into a JsonObject and then post it to my back end (Spring ) and get the field using Json mapper (data.get("Field name").asText;.
I also tried get(index) and data.path but this return null, where as in the debug console It indicates that Json objects were received, what is it that makes these fields to be null?
Is it because this data is not directly from ng-model, or is it because I have pushed it into json object using Angular, because I am getting 400 erro code.
MY ANGULAR JS :
app.controller("OrderOperationsCtrl", function($scope, $http,$window) {
$http.get(productURL).then(function(response) {
$scope.productData = response.data;
$scope.newData = [];
$scope.total = 0.0;
$scope.sync = function(bool,productData,submit){
if(bool === true){
var numberOrdered = 0;
numberOrdered++;
$scope.total = $scope.total + productData.price;
var newD = $scope.newData.push({
"numberOrdered":numberOrdered,
"customerId":localStorage.getItem('takealot_customer'),
"id":productData.id,
"total":$scope.total
});
$scope.sender = $scope.newData;
console.log(" NewD " + $scope.newData);
}
if(submit === true){
$http.put(orderURL,JSON.stringify($scope.sender)).then(function(response){
if(response.data)
console.log("Order created !");
},function(response){
console.log("Error creating Order !");
console.log(response.status);
});
MY SPRING CONTROLLER UPDATE
public ResponseEntity createOrder(#RequestBody OrderOperations[] operation) throws OrderOperationsNotFoundException, IOException{
logger.info("recieved json String " + operation);
services.createOrder(operation);
return new ResponseEntity(HttpStatus.OK);
}
CONSOLE OUTPUT :
Hibernate: select products0_.id as id1_3_, products0_.category as category2_3_, products0_.description as descript3_3_, products0_.name as name4_3_, products0_.price as price5_3_, products0_.quantity as quantity6_3_, products0_.supplier as supplier7_3_ from products products0_
2017-11-03 11:34:41.689 INFO 10504 --- [nio-8080-exec-9]
c.p.C.OrderOperationsController : recieved json String
[{"numberOrdered":1,"customerId":null,"id":1,"total":78.32,"$$hashKey":"object:17"},
{"numberOrdered":1,"customerId":null,"id":2,"total":156.70999999999998,"$$hashKey":"object:19"},
{"numberOrdered":1,"customerId":null,"id":1,"total":235.02999999999997,"$$hashKey":"object:21"}]
THanks in advance
First of all you dont need to map the json into the OrderOperation Object.
Spring will automatically convert the JSON Object into OrderOperations by passing as Parameter
public ResponseEntity createOrder(#RequestBody OrderOperations operation)
And i think you get the Nullpointer while you parsing the Data
Finally I have got a solution. some weeks ago.
- For those who are still struggling to save multiple objects from JSON array
see below ... I hope this helps someone else.
public List<String> createOrder(#RequestBody OrderOperations[] json) throws OrderOperationsNotFoundException, IOException{
logger.info("recieved json String " + json);
List<String> response = new ArrayList<String>();
for(OrderOperations op : json){
services.createOrder(op);
response.add("saved order : " + op.toString());
}
return response;
}
I can use ajax to check infomation in database with jquery but I dont know do same with angularjs . I use
$http({
type : "post",
dataType : "JSON",
url : "register.php",
data : data,
success : function(result)
{
....
}
php code
$errors = array(
'error' => 0
);
$username = $_POST['username']
$password = $_POST['password']
$email =$_POST['email']
$fullname = $_POST['fullname']
$sql = "SELECT * "
. "FROM USERS "
. "WHERE username='".$username."' "
. "OR email='".$email."'";
if (mysqli_num_rows($result) > 0)
{
$row = mysqli_fetch_assoc($result);
if ($row['username'] == $username){
$errors['username'] = 'Tên đăng nhập đã tồn tại';
}
if ($row['email'] == $email){
$errors['email'] = 'Email đã tồn tại';
}
}
if (count($errors) > 1){
$errors['error'] = 1;
die (json_encode($errors));
}else{
//insert database
}
$result = mysqli_query($conn, $sql);
but I dont know do next step . I want check in database if have user name show message error else show succes .Pls help me
Using success is deprecated but you're on the right path. Here's how you would do it now:
$http({
type : "post",
url : "register.php",
data : data
}).then(function(response){
// If data is returned, do stuff with it here
console.log('Yay, my data was POSTed', response.data);
}, function(response){
console.log('Aww, it failed.');
});
It would be easier to help you further, if you add a bit more information on what you're actually trying to achieve. For instance what is returned by this "register.php" endpoint, and what you intent to do after this.
check the DOC for $http.
The $http service is a function which takes a single argument — a configuration object — that is used to generate an HTTP request and returns a promise.
The response comes under promise (.then).
$http({
type : "POST",
url : "register.php",
data : data,
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available/success
console.log(response.data)
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log(response.data)
});
I am making a rest API call using Angular. My Rest API look like as below:
#RequestMapping(value = "/getPDF/{projectId}", method = RequestMethod.POST)
public ResponseEntity<byte[]> generateReport(#PathVariable("projectId") long projectId, #RequestBody Object vo, final HttpServletRequest request) {
vo.setProjectId(projectId);
byte[] pdf = blueprintService.generateBluePrint(vo);
LOG.debug(new StringBuilder("Generating Blueprint for VO: ").append(vo).toString());
String fileName = null;
try {
ProjectDetailsVO pdvo = projectSetupService.getProjectDetails(vo.getProjectId());
fileName = new StringBuilder(pdvo.getClientName()).append("_")
.append(pdvo.getProjectName()).append("_")
.append(System.currentTimeMillis()).append(".pdf")
.toString();
} catch (Exception e) {
}
if (fileName == null || fileName.trim().isEmpty())
fileName = new StringBuilder("Project_")
.append(vo.getProjectId()).append("_")
.append(System.currentTimeMillis())
.append(".pdf").toString();
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/pdf");
String userAgent = request.getHeader("User-Agent");
if (userAgent != null && !(userAgent.contains("Firefox") && userAgent.contains("Mac"))) {
LOG.debug("Inline BP Content");
headers.add("Content-Disposition", new StringBuilder("inline; filename=\"").append(fileName).append("\"").toString());
} else {
LOG.debug("Attached BP Content");
headers.add("Content-Disposition", new StringBuilder("attachment; filename=\"").append(fileName).append("\"").toString());
}
if (pdf != null)
headers.setContentLength(pdf.length);
return new ResponseEntity<byte[]>(pdf, headers, HttpStatus.OK);
}
}
So server is setting file name for the PDF which I want to be the name of the generated PDF.
I tried below angular code:
success: function (data, status, headers, config) {
$modalInstance.close();
var file = new Blob([data], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
}
It works fine but it open the pdf of it's own name. Which I think, since Angular is converting the response into PDF. Hence Headers are getting excluded.
Is there any way to make a post request so it will open a PDF in new browser tab some code like as below:
$http.post{
url: myRestURL,
data: postbodyData,
taget: _blank
}
which will open my rest URL in new tab and show the PDF in browser.
Thank you.