Spring Boot MVC -> Excel data corrupted on download - spring-mvc

I am using ModelAndView pattern to return excel representation of data that is generated in the Controller using Apache POI library.
However the excel gets corrupted(special characters are replaced with ?) when it gets downloaded. If I write the excel to file before pushing it out on the HTTP response, then a valid excel is output.
Here is the controller code that pushes control to ModelAndView
Map<String, Object> model = new HashMap<String, Object>();
model.put(ExcelBusinessReportView.KEY_REPORT_DISPLAY_DATA, reportData);
model.put(ExcelBusinessReportView.KEY_REPORT_DATE, reportRequestDTO.getReportDateUTCAtMidnight());
return new ModelAndView("excelBusinessReportView", model);
And here is the view class
#Service(value = "excelBusinessReportView")
public class ExcelBusinessReportView extends AbstractXlsView {
public static final String KEY_REPORT_DISPLAY_DATA = "reportData";
public static final String KEY_REPORT_DATE = "reportDate";
private static final String MIME_TYPE_EXCEL = "application/ms-excel";
private static final String HEADER_VALUE_CONTENT_DISPOSITION = "attachment; filename=qup_report.xls";
private static final String[] SUMMARY_HEADERS = ........
private static final String[] DETAIL_HEADERS = ........
#Override
protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request,
HttpServletResponse response) throws Exception {
BusinessSlotReportResource reportDisplayData = (BusinessSlotReportResource) model.get(KEY_REPORT_DISPLAY_DATA);
DateTime reportDate = (DateTime) model.get(KEY_REPORT_DATE);
// Build excel document
Sheet sheet = workbook.createSheet(reportDate.toString(CommonConstants.IST_DATE_FORMATTER_PATTERN));
sheet.setDefaultColumnWidth((short) 12);
Integer currentRow = 0;
// Build summary data
currentRow = this.buildSummaryData(workbook, sheet, reportDisplayData, currentRow);
// Create margin rows
sheet.createRow(currentRow++);
sheet.createRow(currentRow++);
// Build detail data
this.buildDetailsData(workbook, sheet, reportDisplayData, currentRow);
response.setContentType(MIME_TYPE_EXCEL);
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, HEADER_VALUE_CONTENT_DISPOSITION);
}
Content of excel when written to file in the view
–œ‡°±·;˛ˇ ˛ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇRoot Entryˇˇˇˇˇˇˇˇ#Workbookˇˇˇˇˇˇˇˇˇˇˇˇ˛ˇˇˇ˝ˇˇˇ˛ˇˇˇ ˛ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ
 !"#$%&'()*+,-./0˛ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ ”ÃA·∞¡‚\panilallewar
Same part of the excel when downloaded
��ࡱ�;�� ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Root Entry��������#Workbook������������������������ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
 !"#$%&'()*+,-./0�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ��A����\panilallewar

Usually instead of putting the file in the model I write it directly in the response.
The following code is for xlsx format, but the concept is the same for previous versions of excel.
This endpoint is accepting a JSON which will be mapped to MyPojo.
#RequestMapping(value = "exportToExcel", method = RequestMethod.POST)
public #ResponseBody HttpEntity<byte[]> generateExcel(#Valid #RequestBody final MyPojo data) throws IOException {
final File file = File.createTempFile("MyExcelReport", "xlsx");
file.deleteOnExit();
final Path path = file.toPath();
try (final FileOutputStream fileOut = new FileOutputStream(file)) {
try (final XSSFWorkbook workbook = new XSSFWorkbook()) {
final XSSFSheet sheet = workbook.createSheet(SHEET_NAME);
//fill your excel sheets
workbook.write(fileOut);
final byte[] byteArray = Files.readAllBytes(path);
final HttpHeaders header = new HttpHeaders();
header.setContentType(new MediaType("application", "vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
header.set("Content-Disposition", "inline; filename=MyExcelReport.xlsx");
header.setContentLength(byteArray.length);
return new HttpEntity<>(byteArray, header);
} catch (final Exception e) {
LOG.error("Error during creation of excel report", e);
throw e;
} finally {
if (path != null) {
try {
Files.delete(path);
} catch (final IOException e) {
LOG.error("Unable to delete file:" + path.toString(), e);
}
}
}
}
}
Also if you are using a frontend framework like angular you have to properly setup the response type (https://stackoverflow.com/a/52703842/3657208)

Related

I am getting null for the one of the column value after extraction. What's wrong with the following program?

I am getting null for one of the selected column with IterableCSVToBean<MessageFileExtractHeader>
DTO Classe:
public class MessageFileExtractHeader implements Serializable {
private static final long serialVersionUID = -3052197544136826142L;
private String mesgid;
private String mesg_type;
// getters and setters
Main Class:
public class FileExtraction {
public static void main(String[] args) throws IOException, IllegalAccessException, InvocationTargetException, InstantiationException, IntrospectionException, CsvBadConverterException, CsvDataTypeMismatchException, CsvRequiredFieldEmptyException, CsvConstraintViolationException {
Properties prop = new Properties();
ExtractFieldUtils efUtils= new ExtractFieldUtils();
MessageFileExtractHeader msgFilxtractRecord = null;
try {
InputStream inputStream =
SAADumpFileExtraction.class.getClassLoader().getResourceAsStream("config.properties");
prop.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
String fileDirectory= prop.getProperty("file.directory");
//get the filenames
String mesgfilename= fileDirectory+prop.getProperty("mesg.file.name");
//get the headers
String mesgheader= fileDirectory+prop.getProperty("mesg.file.header.fields");
int msgskiplines=1;
CSVReader reader = null;
try {
reader = new CSVReader(new FileReader(mesgfilename));
Map<String, String> msgmapping = efUtils.getMapping(mesgheader);
HeaderColumnNameTranslateMappingStrategy<MessageFileExtractHeader> strategy = new HeaderColumnNameTranslateMappingStrategy<MessageFileExtractHeader>();
strategy.setType(MessageFileExtractHeader.class);
strategy.setColumnMapping(msgmapping);
IterableCSVToBean<MessageFileExtractHeader> msgCTBIterator= new IterableCSVToBean<MessageFileExtractHeader>(reader, strategy, null);
Iterator<MessageFileExtractHeader> mesgIterator= msgCTBIterator.iterator();
while(mesgIterator.hasNext()){
msgFilxtractRecord = mesgIterator.next();
System.out.println(msgFilxtractRecord);
//
}} finally {
reader.close();
}
}
}
Output:
MessageFileExtractHeaders [mesgid=null, mesg_type=081]
Please suggest me good solution to get the mesgid.
Please send an short sample of your csv file (header and one line) and the value of your header property.
My guess is there is a type in either the csv header, the headers in the property or both and it does not match what is in the DTO (mesgid). Because of that it will not be populated.

If I have a spring mvc rest controller returning byte[], how would I download to my android app using volley?

I need to implement a list view containing a thumbnail, and this thumbnail is loaded using volley networkimageview. How would I implement this if my controller looks like this:
#RequestMapping (value="/rest/getphoto/", produces=MediaType.IMAGE_PNG_VALUE)
public #ResponseBody byte [] get Image (#RequestParam ("imageId"));
I've found many examples regarding the usage of volley but they are not helping me. Besides, I am using secure connection. Thanks in advance.
EDIT: I'm including controller code in my spring mvc project and the portion of code in my android client requesting an image.
* Spring MVC *
#RequestMapping(value = "/rest/singlephoto/", method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
public #ResponseBody byte[] base64ImageForAndroid(#RequestParam("photoId") String photoIdParam, HttpServletRequest request)
{
String pathToLoad = "/path/default.png";
//HashMap<String, String> retVal = new HashMap<String, String>();
byte[] retVal;
try
{
long photoId = Long.parseLong(photoIdParam);
Photo photo = photoManager.getSinglePhoto(photoId);
if (photo != null)
pathToLoad = photo.getPath();
}
catch (NumberFormatException ex)
{
}
finally
{
try
{
File file = new File(pathToLoad);
retVal = FileUtils.readFileToByteArray(file);
}
catch (IOException ex)
{
retVal = null;
}
}
return retVal;
* Android Client Requesting with volley *
Bitmap thumb = imageCache.get(item.getThumbnailUrl() + "thumb");
if (thumb == null)
{
HttpHeaders headers = new HttpHeaders();
HttpBasicAuthentication auth = new HttpBasicAuthentication(this.username, this.password);
headers.setAuthorization(auth);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_OCTET_STREAM));
Listener<byte[]> imageLoadedListener = new Response.Listener<byte[]>() {
#Override
public void onResponse(byte[] photoByteArray) {
Bitmap bitmap = EfficientImageLoading.decodeBitmapFromByteArray(photoByteArray, viewHolder.thumbnail.getWidth(), viewHolder.thumbnail.getHeight());
viewHolder.thumbnail.setImageBitmap(bitmap);
imageCache.put(item.getThumbnailUrl() + "thumb", bitmap);
//Cache full size and recycle
Bitmap fullBmp = EfficientImageLoading.decodeImageFromByteFullSize(photoByteArray);
imageCache.put(item.getThumbnailUrl(), fullBmp);
}
};
ErrorListener errorListener = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
viewHolder.thumbnail.setImageResource(R.drawable.ic_launcher);
}
};
this.singleInstance.addToRequestQueue(new CustomImageRequest(Request.Method.GET, item.getThumbnailUrl(), errorListener, headers, imageLoadedListener));
}
Application server logs show:
GET /app//photo/rest/singlephoto/?photoId=7 HTTP/1.1" 406 1067
That is 406-- forbidden or something like that. Also android's LogCat shows an error like the following: BasicNetwork.PerformRequest: Unexpected response code 406 for https://domain/app/singlephoto?photoId=7
Is there something wrong with my controller or my client or both?

How to go from spring mvc multipartfile into zipinputstream

I have a Spring MVC controller that accepts a MultipartFile, which will be a zip file. The problem is I can't seem to go from that to a ZipInputStream or ZipFile, so that I can go through the entries. It either closes the stream prematurely, produces an empty file, or as in the case below, zipInputStream.getNextEntry() returning null.
This is my MVC controller:
#RequestMapping(value = "/content/general-import", method = RequestMethod.POST)
public ModelAndView handleGeneralUpload(
#RequestParam("file") MultipartFile file) throws IOException {
// hard code the signature for the moment
String signature = "RETAILER_GROUP:*|CHANNEL:*|LOCALE:de-AT|INDUSTRY:5499";
LOG.info("Processing file archive: {} with signature: {}.", file.getName(), signature);
ModelAndView mav = new ModelAndView();
mav.setViewName("contentUpload");
LOG.debug("File={} is empty={}.", file.getName(), file.isEmpty());
if (!file.isEmpty()) {
processFileZipEntry(file, signature);
mav.addObject("form", UploadViewModel.make("/content/general-import", "Updated content with file"));
return mav;
} else {
mav.addObject("form", UploadViewModel.make("/content/general-import", "Could not update content with file"));
return mav;
}
}
It delegates to the following method for processing:
protected void processFileZipEntry(MultipartFile file, String signature) throws IOException {
byte[] bytes = file.getBytes();
LOG.debug("Processing archive with bytes={}.", file.getBytes().length);
ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(bytes));
LOG.debug("Processing archive with size={}.", file.getSize());
ZipEntry entry = null;
while ((entry = zis.getNextEntry()) != null) {
LOG.debug("Processing file={} is directory?={}.", entry.getName(), entry.isDirectory());
// process each file, based on what it is and whether its a directory etc.
if (!entry.isDirectory()) {
// if the entry is a file, extract it
LOG.debug("Processing entry: {}",entry.getName());
int length = (int) entry.getSize();
Content contentToSave = null;
if(entry.getName().contains("gif")) {
contentToSave = Content.makeImage(entry.getName(), Content.GIF, signature, getBytesFrom(zis, "gif"));
} else if (entry.getName().contains("png")) {
contentToSave = Content.makeImage(entry.getName(), Content.PNG, signature, getBytesFrom(zis, "png"));
} else if (entry.getName().contains("jpeg")) {
contentToSave = Content.makeImage(entry.getName(), Content.JPEG, signature, getBytesFrom(zis, "jpeg"));
} else if (entry.getName().contains("json")) {
contentToSave = Content.makeFile(entry.getName(), Content.JSON, signature, getStringFrom(zis, length));
} else if (entry.getName().contains("js")) {
contentToSave = Content.makeFile(entry.getName(), Content.JS, signature, getStringFrom(zis, length));
} else if (entry.getName().contains("css")) {
contentToSave = Content.makeFile(entry.getName(), Content.CSS, signature, getStringFrom(zis, length));
}
Content contentAleadyThere = contentService.fetch(entry.getName());
if(contentAleadyThere != null) {
LOG.warn("Replacing file: {} with uploaded version.", contentToSave.getName());
}
contentService.put(contentToSave);
LOG.info("Persisted file: {} from uploaded version.", contentToSave.getName());
}
}
}
Basically, in this permutation, the file bytes are there, but there are no entries (zis.getNextEntry() does not exist. I can see that the zip file contains files, and the byte[] has about 3MB worth of stuff, so something must be going wrong with the streaming. Does anyone have a recipe for going from MultipartFile to ZipFile or ZipInputStream?
EDIT
To give you more information, I have a test harnass around this code, by using a MockMvc
#Test
public void testProcessingGeneralUpload() throws Exception {
Resource template = wac.getResource("classpath:lc_content/content.zip");
System.out.println("template content length: " + template.contentLength());
System.out.println("template path: " + template.getFile().getPath());
System.out.println("template filename: " + template.getFilename());
MockMultipartFile firstFile = new MockMultipartFile(
"file", "content.zip", MediaType.APPLICATION_OCTET_STREAM_VALUE, extractFile(template.getFile()));
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.fileUpload("/content/general-import")
.file(firstFile))
.andExpect(status().isOk())
.andExpect(view().name("contentUpload"))
.andExpect(model().attributeExists("form")).andReturn();
// processing assertions
ModelMap modelMap = mvcResult.getModelAndView().getModelMap();
Object object = modelMap.get("form");
assertThat(object, is(not(nullValue())));
assertThat(object, is(instanceOf(UploadViewModel.class)));
UploadViewModel addModel = (UploadViewModel) object;
assertThat(addModel.getMessage(), is(notNullValue()));
assertThat(addModel.getPostUrl(), is(notNullValue()));
assertThat(addModel.getPostUrl(), is("/content/general-import"));
assertThat(addModel.getMessage(), is("Updated content with file"));
// persistence assertions
assertThat(contentDao.findByName("/content/control/basket-manager.js"), is(notNullValue()) );
}
The extractFile method is as follows:
private byte[] extractFile(File zipFile) throws IOException {
ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFile));
System.out.println("length of file: " + zipFile.length());
byte[] output = null;
try {
byte[] data = new byte[(int)zipFile.length()];
zipIn.read(data);
zipIn.close();
output = data;
} catch (IOException e) {
e.printStackTrace();
}
return output;
}
The length of bytes it produces is 3617817, which is the size I expect, and this is fed into the controller method at the top of this question.
I have continued working the problem. The size of the file is correct, it is a zipped file (it unpacks via the OS perfectly), and yet no ZipEntry enumeration.
I would for starters rewrite some of the code instead of doing things in memory with additional byte[].
You are using Spring's Resource class so why not simply use the getInputStream() method to construct the MockMultipartFile as you want to upload that file.
Resource template = wac.getResource("classpath:lc_content/content.zip");
MockMultipartFile firstFile = new MockMultipartFile(
"file", "content.zip", MediaType.APPLICATION_OCTET_STREAM_VALUE, template.getInputStream());
The same for your upload processing code the ZipInputStream can also be constructed on another InputStream which is also provided by the MultipartFile interface.
protected void processFileZipEntry(MultipartFile file, String signature) throws IOException {
LOG.debug("Processing archive with size={}.", file.getSize());
ZipInputStream zis = new ZipInputStream(file.getInputStream());
Wouldn't be the first time that jugling around with byte[] gives a problem. I also vaguely recall some issues with ZipInputStream which lead us to use ZipFile but for this you will first have to store the file in a temp directoy using the transferTo method on MultipartFile.
File tempFile = File.createTempFile("upload", null);
file.transferTo(tempFile);
ZipFile zipFile = new ZipFle(tempFile);
// Proces Zip
tempFile.delete();

Problems while trying to add an xml file to Alfresco

Am facing an issue with Alfresco and honestly am not expert with this type of technology:
the idea is to add an xml file under a folder
the code is like that:
//with the static values are:
public static final String SUSPENDRE_DESUSPENDRE_CONTENT_NAME = "suspendreDesuspendre";
private static final String SUSPENDRE_DESUSPENDRE_CONTENT_TYPE = "text/xml";
private static final String SUSPENDRE_DESUSPENDRE_CONTENT_ENCODING = "UTF-8";
private static final ContentFormat SUSPENDRE_DESUSPENDRE_CONTENT_FORMAT = new ContentFormat(SUSPENDRE_DESUSPENDRE_CONTENT_TYPE,SUSPENDRE_DESUSPENDRE_CONTENT_ENCODING);
private static final byte[] SUSPENDRE_DESUSPENDRE_CONTENT_INITIAL_BYTES = "<?xml //version=\"1.0\" encoding=\"UTF-8\"?><suspendreDesuspendre></suspendreDesuspendre>".getBytes();
#Override
public void createOrUpdateHisSuspendre(ContractBean contractbean,SuspendreDesuspendreEntree suspendreDesuspendreEntree) throws Exception
{
String parentUuid=contractbean.getUuid();
contractDAO.createAlfrescoContent(parentUuid, SUSPENDRE_DESUSPENDRE_CONTENT_NAME, SUSPENDRE_DESUSPENDRE_CONTENT_INITIAL_BYTES, SUSPENDRE_DESUSPENDRE_CONTENT_FORMAT);
}
public Reference createAlfrescoContent(String folderUuid, String contentName,byte[] contentBytes,ContentFormat contentFormat)throws RepositoryFault, RemoteException {
ParentReference parentReference = new ParentReference(new Store(Constants.WORKSPACE_STORE, "SpacesStore"), folderUuid, null, Constants.ASSOC_CONTAINS, "{" + Constants.NAMESPACE_CONTENT_MODEL + "}" + contentName);
NamedValue[] properties = new NamedValue[]{Utils.createNamedValue(Constants.PROP_NAME, contentName)};
CMLCreate create = new CMLCreate("1", parentReference, null, null, null,
Constants.TYPE_CONTENT, properties);
CML cml = new CML();
cml.setCreate(new CMLCreate[]{create});
UpdateResult[] result = WebServiceFactory.getRepositoryService().update(cml);
Reference newContentNode = result[0].getDestination();
Content content = WebServiceFactory.getContentService().write(newContentNode, Constants.PROP_CONTENT, contentBytes, contentFormat);
return content.getNode();
}
the error is:
The association source type is incorrect:
Source Node: workspace://SpacesStore/d4ffbff4-6bd6-4945-948e-2c16c1990cb9
Association: Association[ class=ClassDef[name={http://www.alfresco.org/model/content/1.0}folder], name={http://www.alfresco.org/model/content/1.0}contains, target class={http://www.alfresco.org/model/system/1.0}base, source role=null, target role=null]
Required Source Type: {http://www.alfresco.org/model/content/1.0}folder
Actual Source Type: {com.genia.cnas.alfresco.model}contratDefenseur

JasperReports: Calling report from servlet [duplicate]

This question already has answers here:
JasperReports: How to call the report in jsp page
(6 answers)
Closed 6 years ago.
I'm new to JasperReports and dont know how to call jasper file from servlet. My report contains the pie chart.
You can prepare the Jasper file and stream it to the client.
bytes[] byteStream = JasperRunManager.runReportToPdf("myJasperReport.jasper",paramMap,databaseConn);
OutputStream outStream = servletResponse.getOutputStream();
response.setHeader("Content-Disposition","inline, filename=myReport.pdf");
response.setContentType("application/pdf");
response.setContentLength(byteStream.length);
outStream.write(bytes,0,bytes.length);
Here is a dummy report created within a Servlet file.
It is the same as it would be in normal Java class.
Just make sure you have the imports for your jasper report classes at the top of the file.
The bellow example builds a report from an XML datasource.
public class JasperServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
try {
String reportFile = "myJasperReport.jrxml";
File outputFile = new File("Report.pdf");
HashMap hm = new HashMap();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory
.newDocumentBuilder();
Document document = documentBuilder.parse(new File("myXml.xml"));
// Compile the report
JasperReport report = JasperCompileManager
.compileReport(reportFile);
JRXmlDataSource xml = new JRXmlDataSource(document, "/xml/root");
// Fill the report
JasperPrint print = JasperFillManager.fillReport(report, hm, xml);
// Create an Exporter
JRExporter exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.OUTPUT_FILE, outputFile);
exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
// Export the file
exporter.exportReport();
} catch (Exception e) {
e.printStackTrace();
}
}
}
A complete way to do this from the servlet would be:
public void myServletMethod(HttpServletRequest request, HttpServletResponse response) throws IOException{
JasperReport jasperReport = null;
JasperDesign jasperDesign = null;
Map parameters = new HashMap();
String path = getServletContext().getRealPath("/WEB-INF/");
jasperDesign = JRXmlLoader.load(path+"/relative/path/to/MyReport.jrxml");
jasperReport = JasperCompileManager.compileReport(jasperDesign);
byte[] byteStream = JasperRunManager.runReportToPdf(jasperReport, parameters, **new DataSourceOfYourPreference**);
OutputStream outStream = response.getOutputStream();
response.setHeader("Content-Disposition","inline, filename=myReport.pdf");
response.setContentType("application/pdf");
response.setContentLength(byteStream.length);
outStream.write(byteStream,0,byteStream.length);
}

Resources