Uploading excel file using Jersey and Apache POI - Getting ZIP Exception - Invalid stored block lengths - jersey

I have a REST endpoint written using Jersey that looks like this where I'm trying to upload an excel file and read its contents using Apache POI
#Path("/batch")
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_JSON)
public Response batchUploadAssets(#HeaderParam(HttpHeaders.AUTHORIZATION) final String authorizationHeader,
#HeaderParam(CustomVamsHeaders.ORGANISATION) final Integer vamsOrg,
final FormDataMultiPart formDataMultiPart,
#Context final ContainerRequestContext request) {
BodyPart bodyPart = formDataMultiPart.getBodyParts().get(0);
final BodyPartEntity entity = (BodyPartEntity) bodyPart.getEntity();
InputStream inputStream = entity.getInputStream();
XSSFWorkbook workbook = new XSSFWorkbook(inputStream); -> This line throws the exception below
}
Exception StackTrace
java.util.zip.ZipException: invalid stored block lengths
at org.apache.commons.compress.archivers.zip.ZipArchiveInputStream.readFromInflater(ZipArchiveInputStream.java:586)
at org.apache.commons.compress.archivers.zip.ZipArchiveInputStream.readDeflated(ZipArchiveInputStream.java:551)
at org.apache.commons.compress.archivers.zip.ZipArchiveInputStream.read(ZipArchiveInputStream.java:458)
at java.io.FilterInputStream.read(FilterInputStream.java:133)
at org.apache.poi.openxml4j.util.ZipArchiveThresholdInputStream.read(ZipArchiveThresholdInputStream.java:78)
.......
.......
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:307)
It works fine when I run my app on my local tomcat instance. However, when I deploy my app to an EC2 instance and access it via AWS API Gateway, that's when I get this error. Any idea what I need to do differently?

Related

call api to upload file with metadata using feign client

I created a simple api to upload a file with its metadata using spring boot, the api works fine without any problems, here is the controller :
#PostMapping(value="/v1/docs", consumes=MediaType.MULTIPART_FORM_DATA_VALUE)
public String uploadFile(#ModelAttribute MetaData metadata, #RequestParam("file") MultipartFile file){
// upload file logic ...
return "id";
}
you can see how I call this api using postman :
I deployed this api and now I want to call it in another service (developed also by spring boot), I should use feing client to do this call, so I created a simple feign client :
#FeignClient(name = "docsClient", url="<host_url>")
public interface DocsClient{
#PostMapping(value="/v1/docs", consumes=MediaType.MULTIPART_FORM_DATA_VALUE)
String uploadFile(#RequestParam("file") MultipartFile file, #ModelAttribute MetaData metadata);
}
the proleme is when I call DocsClient.uploadFile, I got an error (415, unsupported mediaType) from the deployed service, when I log the request I found that the depoloyed service get the request like this :
POST /v1/docs?file=<value_of_file>
normally It should not include file or metadata at the url, but it should include it as --form instead:
--form "key=value"
How can I solve this issue?
The order of parameters matter, when creating the client you should respect the order :
#FeignClient(name = "docsClient", url="<host_url>")
public interface DocsClient{
#PostMapping(value="/v1/docs", consumes=MediaType.MULTIPART_FORM_DATA_VALUE)
String uploadFile( #ModelAttribute MetaData metadata, #RequestParam("file") MultipartFile file);
}

Chunk by chunk large file upload using java rest api

I am writing a module in Microservices, where I have to write a rest end point to upload large files chunk by chunk and save each chunk in local tmp directory.. Will get input as chunk of video file.
I am using Java11, Jetty server, SpringBoot framework.
I have written a piece of code in controller as below:
#Named
#Singleton
#Path("/chunk")
public class FileUploadChunkController {
#POST
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_OCTET_STREAM})
#Path("/uploadvideo")
public Response uploadVideo(#FormDataParam("file")InputStream inputStream, #FormDataParam("file") FormDataContentDisposition contentDisposition , #Context final HttpServletRequest request) throws Exception {
LOGGER.info("Inside method: uploadVideo");
}
When invoking the api with chunk file as data, it is not reaching to the controller POST method.
Could some one help me?
I have spent lot of time but did not get solution for it.

File-upload fails when called via a service i.e restTemplate.postForEntity

I have below springboot rest end point to upload files.
#RequestMapping(
method = RequestMethod.POST,
value = "/v1/file-upload",
consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Response> uploadFile (
#RequestParam(value = "multipartFile") MultipartFile multipartFile) throws IOException {
String str = storeFile(multipartFile);
return new ResponseEntity<>(new Response("successfully uploaded with name "+str), HttpStatus.OK);
}
and properties as below
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=30MB
this API when called via postman, working fine.
but when called via restTemplate from a service, it's throwing
{"timestamp":"2020-05-26T09:17:46.369+0000","status":500,"error":"Internal Server Error","message":"Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException: The field multipartFile exceeds its maximum permitted size of 1048576 bytes.","path":"/43c0800d-b992-45b6-8d25-9e81115539d0/Form/files/mock/api/v1/file-upload"}
exception.
my service calls as below
apiCallResponseObj = restClientUtil.postEntity(serviceUrl, Object.class, apiEndPoint.getFormData(), headers);
apiEndPoint.getFormData() has the multipart file data.
my question is, why am I getting an exception when called via a service?
using springboot 2.1.13
the issue was with api-gateway (kong) where the limitations were put.
the configurations given in the question works fine.

google drive Oauth 2.0 for java web application

My project is a java spark project that I have hosted on heroku. A part of the project requires that I download a particular file from my google drive into the application. I managed to set up everything when my application was running locally but as soon as I deployed the app it stopped working. This was regardless of the fact that when the app was running locally I used an Oauth2 client ID of type other and when I deployed the application I created a new one of type web application.
Below is a snippet of the authentication and download code:
public class AutoCalls {
/** Application name. */
private static final String APPLICATION_NAME = "calls-made";
private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("target/classes/auth"), ".credentials/calls-made");
private static FileDataStoreFactory DATA_STORE_FACTORY;
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static HttpTransport HTTP_TRANSPORT;
private static final List<String> SCOPES = Arrays.asList(DriveScopes.DRIVE);
static {
try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
} catch (GeneralSecurityException | IOException t) {
System.exit(1);
}
}
public static void startDownload() throws IOException, ParseException {
Drive serv = getDriveService();
// drive stuff deleted
}
public static Credential authorize() throws IOException {
InputStream in = new FileInputStream("target/classes/auth/client_secret_*****************************************.apps.googleusercontent.com.json");
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(DATA_STORE_FACTORY)
.setAccessType("offline")
.build();
Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
System.out.println("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
return credential;
}
public static Drive getDriveService() throws IOException {
Credential credential = authorize();
return new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME)
.build();
}
}
Currently when I try to initiate the download I get a URL in the Heroku logs a follows:
2017-02-20T10:32:28.656820+00:00 app[web.1]: Please open the following address in your browser:
2017-02-20T10:32:28.656908+00:00 app[web.1]: https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=************-vvdi7u6bmp1vc90sdidtnuiftdi1t49c.apps.googleusercontent.com&redirect_uri=http://localhost:48085/Callback&response_type=code&scope=https://www.googleapis.com/auth/drive
When I try open the URL in a browser I get an error:
Error: redirect_uri_mismatch
I cannot find any good step by step tutorial on accessing google drive contents on a java web application so any help would be arreiciated.
Generally, if OAuth works on server-A but not on server-B, it's because the redirect URL hasn't been configured correctly on the API Console. There is no reason why you would need to use a different client-ID because a single client-ID can be configured with multiple URLs, eg your local host and your heroku server. Another possibility is the use of https.
There is a separate problem in your code where you iterate on lista.isEmpty(). You should be iterating on nextPageToken != null. See the answer to Google drive rest API, Download files from root folder only

CUCM AXL API wrong SoapAction

I want to make SQL query to CUCM DB. I generated Java classes from WSDL with Maven jaxb2 plugin, but Cisco AXL docs advice to use wsdl2java. I've got lot of Java classes with Req/Res endings (request and response as I understand). This is my code:
public class CUCMDatabaseConnector extends WebServiceGatewaySupport{
private String SOAP_ACTION = "CUCM:DB ver=10.5";
public void updateData(){
String END_USERS_REQUEST = REQUEST,
AXLurl = "https://" + properties.getCurrentCUCM_IP() + ":8443/axl/";
ExecuteSQLQueryReq sqlRequest = new ExecuteSQLQueryReq();
sqlRequest.setSql(END_USERS_REQUEST);
WebServiceTemplate template = getWebServiceTemplate();
template.setMessageSender(NullHostnameVerifier.getMessageSender());
ExecuteSQLQueryRes sqlResponse = (ExecuteSQLQueryRes) template
.marshalSendAndReceive(
AXLurl,
sqlRequest,
new WebServiceMessageCallback() {
#Override
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
TransportContext context = TransportContextHolder.getTransportContext();
HttpUrlConnection connection = (HttpUrlConnection) context.getConnection();
//adding required headers
connection.addRequestHeader( "SOAPAction", SOAP_ACTION);
connection.addRequestHeader("Authorization", autenString);
}
}
});
}
}
}
But when I run it, I get error:
org.springframework.ws.soap.client.SoapFaultClientException: The endpoint reference (EPR) for the Operation not found is https://IP:8443/axl/services/AXLAPIService and the WSA Action = CUCM:DB ver=10.5 executeSQLQueryReq
So, as I see, problem is CUCM AXL service has executeSQLQuery method, but not executeSQLQueryReq.
How can I make Spring putting correct method in SoapAction? Or I need to use only wsdl2java?
UPDATE
When I was generating java classes, there was also .xsd schema in the directory. jaxb2 config pointed to WSDL file, however, I've got error URI [src/main/resources/AXLAPI.wsdl] does not provide the scheme part., and It looks like plugin built classes from xsd schema, not wsdl. But this wsdl was original file downloaded from CUCM. What could be wrong?
Found this link on developers.cisco.com. This how-to advices to use AXLPort, a kind of wrapper for making SOAP request to CUCM.
Looks to me, CUCM AXL SOAP interface is not the best choice to start working with Spring WS

Resources