How to prevent < converted to < when using web service proxy class in JDeveloper - web-services

I am calling a BPM web service that sends HTML email. I generated a web service proxy in JDeveloper 11.1.1.7. The type of the body of the email is xsd:string which should map to java String. I understand that certain characters, for example < > &, are reserved and converted during the xml document creation during the proxy operation.
Using SOAPUI to call the service, I can pass the body as <h1>My Heading</h1> and service responds correctly, sending the email with HTML as expected. When doing the same from a POJO that calls the proxy, <h1> is converted to <h1>My heading</h1>.
I have tried passing the body as a CDATA section but this makes no difference. I have tried converting the body to bytes then back to a UTF-8 string before the call but still no difference. I have access to the BPM service code. Is there a way I can send html to the service from a proxy, that retains the special characters?

I figured this out finally. While the JDeveloper web service proxy generator is useful most of the time, in this case it was not since I needed to send xml special characters to the service. Perhaps there is a way to manipulate the proxy code to do what you want but I couldn't figure it out.
Of particular help was this AMIS blog entry. And if you ever need to handle special characters during JAXB marshalling, this entry will help you too. A great summary of the steps to use the java URLConnection class is here and that answer points to a library that would probably make life even easier.
So here is the raw wrapper code below. The particular BPM email service we wrote also writes to a log and that explains the complex types in the raw xml input. Naturally I will populate the email values from a passed in POJO object in the main sendMail wrapper method.
package com.yourdomain.sendmail.methods;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import oracle.adf.model.connection.url.URLConnectionProxy;
import oracle.adf.share.ADFContext;
public class SendMailWrapper {
public SendMailWrapper() {
super();
}
public static void main(String[] args) throws MalformedURLException, IOException {
SendMailWrapper w = new SendMailWrapper();
w.sendMail();
}
public void sendMail() throws MalformedURLException, IOException {
String xmlInput =
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" " +
"xmlns:sen=\"http://xmlns.oracle.com/bpmn/bpmnProcess/SendEmailProcess\" " +
"xmlns:ema=\"http://www.wft.com/BPM/SendEmail/Email\">\n" +
"<soapenv:Header/>" +
"<soapenv:Body>\n" +
"<sen:start>\n" +
"<ema:emailInput>\n" +
"<ema:emailContent>\n" +
"<ema:toAddr>your.name#yourdomain.com</ema:toAddr>\n" +
"<ema:fromAddr></ema:fromAddr>\n" +
"<ema:ccAddr></ema:ccAddr>\n" +
"<ema:bccAddr></ema:bccAddr>\n" +
"<ema:subject>SendMail HTML</ema:subject>\n" +
"<ema:body><h1>My Heading</h1><p>Text</p></ema:body>\n" +
"<ema:contentType>text/html</ema:contentType>\n" +
"</ema:emailContent>\n" +
"<ema:emailHistory>\n" +
"<ema:projectName>Soap Test</ema:projectName>\n" +
"<ema:reqID></ema:reqID>\n" +
"<ema:compositeID></ema:compositeID>\n" +
"<ema:processID></ema:processID>\n" +
"<ema:processName></ema:processName>\n" +
"<ema:activityName></ema:activityName>\n" +
"<ema:insertDate></ema:insertDate>\n" +
"<ema:insertByID></ema:insertByID>\n" +
"<ema:insertByName></ema:insertByName>\n" +
"<ema:commentType></ema:commentType>\n" +
"<ema:commentInfo></ema:commentInfo>\n" +
"</ema:emailHistory>\n" +
"</ema:emailInput>\n" +
"</sen:start>\n" +
"</soapenv:Body>\n" +
"</soapenv:Envelope>\n";
System.out.println(xmlInput);
String wsURL = getWsdlUrl();
URL url = new URL(wsURL);
URLConnection connection = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection)connection;
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] buffer = new byte[xmlInput.length()];
buffer = xmlInput.getBytes();
bout.write(buffer);
byte[] b = bout.toByteArray();
String SOAPAction = "start"; //this is the method in the service
httpConn.setRequestProperty("Content-Length", String.valueOf(b.length));
httpConn.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
//some other props available but don't need to be set...
//httpConn.setRequestProperty("Accept-Encoding", "gzip,deflate");
//httpConn.setRequestProperty("Host", "your.host.com:80");
//httpConn.setRequestProperty("Connection", "Keep-Alive");
//httpConn.setRequestProperty("User-Agent", "Apache-HttpClient/4.1.1 (java 1.5)");
httpConn.setRequestProperty("SOAPAction", SOAPAction);
httpConn.setRequestMethod("POST");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
OutputStream out = httpConn.getOutputStream();
out.write(b);
out.close();
//check response code...
int status = httpConn.getResponseCode();
String respMessage = httpConn.getResponseMessage();
System.out.println("RESPONSE CODE: " + status + " RESPONSE MESSAGE: " + respMessage);
//check response headers...
for (Map.Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
System.out.println(header.getKey() + "=" + header.getValue());
}
//check error stream - this helps alot when debugging...
InputStream errorStream = ((HttpURLConnection)connection).getErrorStream();
if (errorStream != null) {
System.out.println("Error Stream: " + convertStreamToString(errorStream));
}
//if there was an expected response, you need to parse it...
/* String responseString = "";
String outputString = "";
InputStreamReader isr = new InputStreamReader(httpConn.getInputStream());
BufferedReader in = new BufferedReader(isr);
while ((responseString = in.readLine()) != null) {
outputString = outputString + responseString;
}
isr.close();
System.out.println("OUT: " + outputString); */
}
static String convertStreamToString(InputStream is) {
Scanner s = new Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
private static String getWsdlUrl() {
String result = null;
try {
URLConnectionProxy wsConnection = (URLConnectionProxy)ADFContext.getCurrent().getConnectionsContext().lookup("SendMailProxyConnection");
result = wsConnection.getURL().toExternalForm();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
Happy coding.

Related

AWS rekognition Request has invalid image format

I get this error when i try to compare two images from my s3 bucket, i follow the functions rules to get an image from S3Object with correct name and s3 bucket name but i throws the Invalid image format exception. Maybe it has to be as a base64 or bytebuffer? i dont understand then why there is a function to get from S3Object.
My code is simple and as follows:
String reference = "reference.jpg";
String target = "selfie.jpg";
String bucket = "pruebas";
CompareFacesRequest request = new CompareFacesRequest()
.withSourceImage(new Image().withS3Object(new S3Object()
.withName(reference).withBucket(bucket)))
.withTargetImage(new Image().withS3Object(new S3Object()
.withName(target).withBucket(bucket)))
.withSimilarityThreshold(similarityThreshold);
AmazonRekognition rekognitionClient = AmazonRekognitionClientBuilder.standard()
.withRegion(Regions.US_EAST_1).build();
CompareFacesResult compareFacesResult= rekognitionClient.compareFaces(request);
The exception is thrown in compareFaces(request) the last line.
this is main part of the error:
Exception in thread "main" com.amazonaws.services.rekognition.model.InvalidImageFormatException: Request has invalid image format (Service: AmazonRekognition; Status Code: 400; Error Code: InvalidImageFormatException;
The images are in AWS S3 and my credentials for rekognition have permission to read from S3. So in that part is not the error.
UPDATE CODE:
public static void main(String[] args) throws FileNotFoundException {
Float similarityThreshold = 70F;
String reference = "reference.jpg";
String target = "target.jpg";
String bucket = "pruebas";
ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.builder().profileName("S3").build();
Region region = Region.US_EAST_1;
S3Client s3 = S3Client.builder()
.region(region)
.credentialsProvider(credentialsProvider)
.build();
byte[] sourceStream = getObjectBytes(s3, bucket,reference);
byte[] tarStream = getObjectBytes(s3, bucket, target);
SdkBytes sourceBytes = SdkBytes.fromByteArrayUnsafe(sourceStream);
SdkBytes targetBytes = SdkBytes.fromByteArrayUnsafe(tarStream);
Image souImage = Image.builder()
.bytes(sourceBytes)
.build();
Image tarImage = Image.builder()
.bytes(targetBytes)
.build();
CompareFacesRequest request = CompareFacesRequest.builder()
.sourceImage(souImage)
.targetImage(tarImage)
.similarityThreshold(similarityThreshold).build();
RekognitionClient rekognitionClient = RekognitionClient.builder()
.region(Region.US_EAST_2).build();
CompareFacesResponse compareFacesResult= rekognitionClient.compareFaces(request);
List<CompareFacesMatch> faceDetails = compareFacesResult.faceMatches();
for (CompareFacesMatch match: faceDetails){
ComparedFace face= match.face();
BoundingBox position = face.boundingBox();
System.out.println("Face at " + position.left().toString()
+ " " + position.top()
+ " matches with " + face.confidence().toString()
+ "% confidence.");
}
List<ComparedFace> uncompared = compareFacesResult.unmatchedFaces();
System.out.println("There was " + uncompared.size()
+ " face(s) that did not match");
System.out.println("Source image rotation: " + compareFacesResult.sourceImageOrientationCorrection());
System.out.println("target image rotation: " + compareFacesResult.targetImageOrientationCorrection());
}
public static byte[] getObjectBytes (S3Client s3, String bucketName, String keyName) {
try {
GetObjectRequest objectRequest = GetObjectRequest
.builder()
.key(keyName)
.bucket(bucketName)
.build();
ResponseBytes<GetObjectResponse> objectBytes = s3.getObjectAsBytes(objectRequest);
return objectBytes.asByteArray();
} catch (S3Exception e) {
System.err.println(e.awsErrorDetails().errorMessage());
System.exit(1);
}
return null;
}
Try using AWS SDK for Java V2 - not the old V1 lib. Using V2 is strongly recommended over V1 and is best practice.
Here is the V2 code that works fine to compare faces. In this example, notice that you have to get the image into a SdkBytes object. It does not matter where the image is located as long as you get it into SDKBytes. The image can be in an S3 bucket, the local file system. etc.
You can find this V2 Reckonation example in the AWS Github repo here:
https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/rekognition/src/main/java/com/example/rekognition
Also - you can use S3 Java V2 Service client to read an image in an S3 bucket and get the byte[]. From there, you can create an SDKBytes object to use in CompareFaces.
https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/GetObjectData.java
Here is the full Java example for Compare Faces. Notice there is an URL to the Java DEV Guide if you do not know how to get up and running with AWS SDK for Java V2 - including how to set up your creds.
package com.example.rekognition;
// snippet-start:[rekognition.java2.compare_faces.import]
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.rekognition.RekognitionClient;
import software.amazon.awssdk.services.rekognition.model.RekognitionException;
import software.amazon.awssdk.services.rekognition.model.Image;
import software.amazon.awssdk.services.rekognition.model.CompareFacesRequest;
import software.amazon.awssdk.services.rekognition.model.CompareFacesResponse;
import software.amazon.awssdk.services.rekognition.model.CompareFacesMatch;
import software.amazon.awssdk.services.rekognition.model.ComparedFace;
import software.amazon.awssdk.services.rekognition.model.BoundingBox;
import software.amazon.awssdk.core.SdkBytes;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
// snippet-end:[rekognition.java2.compare_faces.import]
/**
* Before running this Java V2 code example, set up your development environment, including your credentials.
*
* For more information, see the following documentation topic:
*
* https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
*/
public class CompareFaces {
public static void main(String[] args) {
final String usage = "\n" +
"Usage: " +
" <pathSource> <pathTarget>\n\n" +
"Where:\n" +
" pathSource - The path to the source image (for example, C:\\AWS\\pic1.png). \n " +
" pathTarget - The path to the target image (for example, C:\\AWS\\pic2.png). \n\n";
if (args.length != 2) {
System.out.println(usage);
System.exit(1);
}
Float similarityThreshold = 70F;
String sourceImage = args[0];
String targetImage = args[1];
Region region = Region.US_EAST_1;
RekognitionClient rekClient = RekognitionClient.builder()
.region(region)
.credentialsProvider(ProfileCredentialsProvider.create())
.build();
compareTwoFaces(rekClient, similarityThreshold, sourceImage, targetImage);
rekClient.close();
}
// snippet-start:[rekognition.java2.compare_faces.main]
public static void compareTwoFaces(RekognitionClient rekClient, Float similarityThreshold, String sourceImage, String targetImage) {
try {
InputStream sourceStream = new FileInputStream(sourceImage);
InputStream tarStream = new FileInputStream(targetImage);
SdkBytes sourceBytes = SdkBytes.fromInputStream(sourceStream);
SdkBytes targetBytes = SdkBytes.fromInputStream(tarStream);
// Create an Image object for the source image.
Image souImage = Image.builder()
.bytes(sourceBytes)
.build();
Image tarImage = Image.builder()
.bytes(targetBytes)
.build();
CompareFacesRequest facesRequest = CompareFacesRequest.builder()
.sourceImage(souImage)
.targetImage(tarImage)
.similarityThreshold(similarityThreshold)
.build();
// Compare the two images.
CompareFacesResponse compareFacesResult = rekClient.compareFaces(facesRequest);
List<CompareFacesMatch> faceDetails = compareFacesResult.faceMatches();
for (CompareFacesMatch match: faceDetails){
ComparedFace face= match.face();
BoundingBox position = face.boundingBox();
System.out.println("Face at " + position.left().toString()
+ " " + position.top()
+ " matches with " + face.confidence().toString()
+ "% confidence.");
}
List<ComparedFace> uncompared = compareFacesResult.unmatchedFaces();
System.out.println("There was " + uncompared.size() + " face(s) that did not match");
System.out.println("Source image rotation: " + compareFacesResult.sourceImageOrientationCorrection());
System.out.println("target image rotation: " + compareFacesResult.targetImageOrientationCorrection());
} catch(RekognitionException | FileNotFoundException e) {
System.out.println("Failed to load source image " + sourceImage);
System.exit(1);
}
}
// snippet-end:[rekognition.java2.compare_faces.main]
}
This code works fine too with JPG images -- as shown in the following image of an IDE debugging the code displaying the results:
UPDATE
I normally do not touch V1 code at all; however, i was curious. This code worked....
package aws.example.rekognition.image;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.rekognition.AmazonRekognition;
import com.amazonaws.services.rekognition.AmazonRekognitionClientBuilder;
import com.amazonaws.services.rekognition.model.Image;
import com.amazonaws.services.rekognition.model.BoundingBox;
import com.amazonaws.services.rekognition.model.CompareFacesMatch;
import com.amazonaws.services.rekognition.model.CompareFacesRequest;
import com.amazonaws.services.rekognition.model.CompareFacesResult;
import com.amazonaws.services.rekognition.model.ComparedFace;
import java.util.List;
import com.amazonaws.services.rekognition.model.S3Object;
public class CompareFacesBucket {
public static void main(String[] args) throws Exception{
Float similarityThreshold = 70F;
AmazonRekognition rekognitionClient = AmazonRekognitionClientBuilder.standard()
.withRegion(Regions.US_WEST_2)
.build();
String reference = "Lam1.jpg";
String target = "Lam2.jpg";
String bucket = "<MyBucket>";
CompareFacesRequest request = new CompareFacesRequest()
.withSourceImage(new Image().withS3Object(new S3Object()
.withName(reference).withBucket(bucket)))
.withTargetImage(new Image().withS3Object(new S3Object()
.withName(target).withBucket(bucket)))
.withSimilarityThreshold(similarityThreshold);
// Call operation
CompareFacesResult compareFacesResult = rekognitionClient.compareFaces(request);
// Display results
List <CompareFacesMatch> faceDetails = compareFacesResult.getFaceMatches();
for (CompareFacesMatch match: faceDetails){
ComparedFace face= match.getFace();
BoundingBox position = face.getBoundingBox();
System.out.println("Face at " + position.getLeft().toString()
+ " " + position.getTop()
+ " matches with " + face.getConfidence().toString()
+ "% confidence.");
}
List<ComparedFace> uncompared = compareFacesResult.getUnmatchedFaces();
System.out.println("There was " + uncompared.size()
+ " face(s) that did not match");
System.out.println("Source image rotation: " + compareFacesResult.getSourceImageOrientationCorrection());
System.out.println("target image rotation: " + compareFacesResult.getTargetImageOrientationCorrection());
}
}
Output:
The last thing that i can think of as my V1 code works with JPG images and yours does not is your JPG image files may be corrupt or something. I would like to test this code with your images.

Unable to use http connector

I'm trying to use the http connector that is provided with the standard Camunda implementation with no luck. Every single time that I run my workflow the instance simply freeze on that activity. I'm using this class in an execution listnener and the code that I'm using is this:
import org.apache.ibatis.logging.LogFactory;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.Expression;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import org.camunda.bpm.engine.impl.util.json.JSONObject;
import org.camunda.connect.Connectors;
import org.camunda.connect.ConnectorException;
import org.camunda.connect.httpclient.HttpConnector;
import org.camunda.connect.httpclient.HttpResponse;
import org.camunda.connect.httpclient.impl.HttpConnectorImpl;
import org.camunda.connect.impl.DebugRequestInterceptor;
public class APIAudit implements JavaDelegate {
static {
LogFactory.useSlf4jLogging(); // MyBatis
}
private static final java.util.logging.Logger LOGGER = java.util.logging.Logger.getLogger(Thread.currentThread().getStackTrace()[0].getClassName());
private Expression tokenField;
private Expression apiServerField;
private Expression questionIDField;
private Expression subjectField;
private Expression bodyField;
public void execute(DelegateExecution arg0) throws Exception {
String tokenValue = (String) tokenField.getValue(arg0);
String apiServerValue = (String) apiServerField.getValue(arg0);
String questionIDValue = (String) questionIDField.getValue(arg0);
String subjectValue = (String) subjectField.getValue(arg0);
String bodyValue = (String) bodyField.getValue(arg0);
if (apiServerValue != null) {
String url = "http://" + apiServerValue + "/v1.0/announcement";
LOGGER.info("token: " + tokenValue);
LOGGER.info("apiServer: " + apiServerValue);
LOGGER.info("questionID: " + questionIDValue);
LOGGER.info("subject: " + subjectValue);
LOGGER.info("body: " + bodyValue);
LOGGER.info("url: " + url);
JSONObject jsonBody = new JSONObject();
jsonBody.put("access_token", tokenValue);
jsonBody.put("source", "SYSTEM");
jsonBody.put("target", "AUDIT");
jsonBody.put("tType", "system");
jsonBody.put("aType", "auditLog");
jsonBody.put("affectedItem", questionIDValue);
jsonBody.put("subject", subjectValue);
jsonBody.put("body", bodyValue);
jsonBody.put("language", "EN");
try {
LOGGER.info("Generating connection");
HttpConnector http = Connectors.getConnector(HttpConnector.ID);
LOGGER.info(http.toString());
DebugRequestInterceptor interceptor = new DebugRequestInterceptor(false);
http.addRequestInterceptor(interceptor);
LOGGER.info("JSON Body: " + jsonBody.toString());
HttpResponse response = http.createRequest()
.post()
.url(url)
.contentType("application/json")
.payload(jsonBody.toString())
.execute();
Integer responseCode = response.getStatusCode();
String responseBody = response.getResponse();
response.close();
LOGGER.info("[" + responseCode + "]: " + responseBody);
} catch (ConnectorException e) {
LOGGER.severe(e.getMessage());
}
} else {
LOGGER.info("No APISERVER provided");
}
LOGGER.info("Exiting");
}
}
I'm sure that the fields injection works correctly since the class prints the correct values. I also used the http-connector in javascript in the same activity with no problem.
I'm using this approach since I need to make two different calls to external REST services in the same task, so any advice will be very welcome.
You need to enable Connect process engine plugin in process engine configuration. Not sure how you configured the process engine, make sure to add this plugin org.camunda.connect.plugin.impl.ConnectProcessEnginePlugin
Also check the following in dependencies
Do not add both dependencies - connectors-all and http-connector.
Make sure to check the error logs and see whether you have any class loading problem related to httpclient classes
I am pretty sure there is a class loading issue with http client library. make sure to include the correct version of connectors-all dependency

Sending Multiple images from web service SPRINGBOOT+REST+MAVEN

I am writing a web service in spring boot restful web App using which i am sending a image to anyone who wants to consume it below is a code snippet which worked for me
#RequestMapping(value = "/photo_1",method = RequestMethod.GET )
public ResponseEntity<byte[]> greeting_image_1(#RequestParam(value="name", defaultValue="World") String name) throws IOException{
InputStream in = getClass().getResourceAsStream("/images/someimage.jpg");
byte[] a = IOUtils.toByteArray(in);
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_JPEG);
return new ResponseEntity<byte[]>(a,headers,HttpStatus.CREATED);
}
This web service works perfectly fine in case i want to return a single image from a web service
But what if in case i want to return array of images(i.e. more than 1 image)
Any help is highly appreciated.
Regards,
Here's the sample code that I wrote to generate a multipart response with multiple images in it. It's properly consumed by Firefox and it prompts to save each image in the response.
public ResponseEntity<byte[]> showImages () throws IOException {
String boundary="---------THIS_IS_THE_BOUNDARY";
List<String> imageNames = Arrays.asList(new String[]{"1.jpg","2.jpg"});
List<String> contentTypes = Arrays.asList(new String[]{MediaType.IMAGE_JPEG_VALUE,MediaType.IMAGE_JPEG_VALUE});
List<Byte[]> imagesData = new ArrayList<Byte[]>();
imagesData.add(ArrayUtils.toObject(IOUtils.toByteArray(getClass().getResourceAsStream("/images/1.jpg"))));
imagesData.add(ArrayUtils.toObject(IOUtils.toByteArray(getClass().getResourceAsStream("/images/2.jpg"))));
byte[] allImages = getMultipleImageResponse(boundary, imageNames,contentTypes, imagesData);
final HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type","multipart/x-mixed-replace; boundary=" + boundary);
return new ResponseEntity<byte[]>(allImages,headers,HttpStatus.CREATED);
}
private static byte[] getMultipleImageResponse(String boundary, List<String> imageNames, List<String> contentTypes, List<Byte[]> imagesData){
byte[] finalByteArray = new byte[0];
Integer imagesCounter = -1;
for(String imageName : imageNames){
imagesCounter++;
String header="--" + boundary
+ "\r\nContent-Disposition: form-data; name=\"" + imageName
+ "\"; filename=\"" + imageName + "\"\r\n"
+ "Content-type: " + contentTypes.get(imagesCounter) + "\r\n\r\n";
byte[] currentImageByteArray=ArrayUtils.addAll(header.getBytes(), ArrayUtils.toPrimitive(imagesData.get(imagesCounter)));
finalByteArray = ArrayUtils.addAll(finalByteArray,ArrayUtils.addAll(currentImageByteArray, "\r\n\r\n".getBytes()));
if (imagesCounter == imageNames.size() - 1) {
String end = "--" + boundary + "--";
finalByteArray = ArrayUtils.addAll(finalByteArray, end.getBytes());
}
}
return finalByteArray;
}
You should implement this depending on the capability of the consumer. If the consumer can parse multipart response, please go ahead with this approach, else consider other options like
Sending a zipped file of all images
Returning a json/xml of image names along with URLs to download them
Returning a json/xml with all images in Base64 encoded string
You may also send a html response with all images embedded in it using the below code. This should work fine in all browsers as it is pure html.
public ResponseEntity<byte[]> getAllImages() throws IOException {
List<String> imageNames = Arrays.asList(new String[]{"1.jpg","2.jpg"});
List<String> contentTypes = Arrays.asList(new String[]{MediaType.IMAGE_JPEG_VALUE,MediaType.IMAGE_JPEG_VALUE});
List<Byte[]> imagesData = new ArrayList<Byte[]>();
imagesData.add(ArrayUtils.toObject(IOUtils.toByteArray(getClass().getResourceAsStream("/images/1.jpg"))));
imagesData.add(ArrayUtils.toObject(IOUtils.toByteArray(getClass().getResourceAsStream("/images/2.jpg"))));
byte[] htmlData=getHtmlData(imageNames,contentTypes, imagesData);
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_HTML);
return new ResponseEntity<byte[]>(htmlData,headers,HttpStatus.OK);
}
private static byte[] getHtmlData(List<String> imageNames, List<String> contentTypes, List<Byte[]> imagesData){
String htmlContent="<!DOCTYPE html><html><head><title>Images</title></head><body>";
Integer imagesCounter = -1;
for(String imageName : imageNames){
imagesCounter++;
htmlContent = htmlContent + "<br/><br/><b>" + imageName + "</b><br/></br/><img src='data:" + contentTypes.get(imagesCounter) + ";base64, " + org.apache.commons.codec.binary.StringUtils.newStringUtf8(Base64
.encodeBase64(ArrayUtils.toPrimitive(imagesData.get(imagesCounter)))) + "'/>";
}
htmlContent = htmlContent + "</body></html>";
return htmlContent.getBytes();
}
You should take a look to "Uploading Files" Spring Boot guide : https://spring.io/guides/gs/uploading-files/
There's a an example of upload and download.

WSO2 MessageBroker:Throwing org.wso2.andes.AMQTimeoutException error when creating durable subscriber

I have a code that acts as my subscriber. I have created durable subscriber. So due to this i am getting exception as
Exception in thread "main" javax.jms.JMSException: Error registering consumer: org.wso2.andes.AMQTimeoutException: Server did not respond in a timely fashion [error code 408: Request Timeout]
at org.wso2.andes.client.AMQSession$4.execute(AMQSession.java:2054)
at org.wso2.andes.client.AMQSession$4.execute(AMQSession.java:1997)
at org.wso2.andes.client.AMQConnectionDelegate_8_0.executeRetrySupport(AMQConnectionDelegate_8_0.java:305)
at org.wso2.andes.client.AMQConnection.executeRetrySupport(AMQConnection.java:621)
at org.wso2.andes.client.failover.FailoverRetrySupport.execute(FailoverRetrySupport.java:102)
at org.wso2.andes.client.AMQSession.createConsumerImpl(AMQSession.java:1995)
at org.wso2.andes.client.AMQSession.createConsumer(AMQSession.java:993)
at org.wso2.andes.client.AMQSession.createDurableSubscriber(AMQSession.java:1142)
at org.wso2.andes.client.AMQSession.createDurableSubscriber(AMQSession.java:1042)
at org.wso2.andes.client.AMQTopicSessionAdaptor.createDurableSubscriber(AMQTopicSessionAdaptor.java:73)
at xml.parser.Parser.subscribe(Parser.java:62)
at xml.parser.Parser.main(Parser.java:34)
But instead od durable when i create normal Subscriber, My code run good and there is no error. Why i am getting this error?
And one more question-How can i unsubscribe from the topic?
My code for Subscriber is:
package xml.parser;
import org.w3c.dom.*;
import javax.xml.xpath.*;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.*;
import java.io.IOException;
import org.xml.sax.SAXException;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Properties;
public class Parser {
public static final String QPID_ICF = "org.wso2.andes.jndi.PropertiesFileInitialContextFactory";
private static final String CF_NAME_PREFIX = "connectionfactory.";
private static final String CF_NAME = "qpidConnectionfactory";
String userName = "admin";
String password = "admin";
private static String CARBON_CLIENT_ID = "carbon";
private static String CARBON_VIRTUAL_HOST_NAME = "carbon";
private static String CARBON_DEFAULT_HOSTNAME = "localhost";
private static String CARBON_BROKER_PORT = "5673";
String topicName = "myTopic";
public static void main(String[] args) throws NamingException,
JMSException, XPathExpressionException,
ParserConfigurationException, SAXException, IOException {
Parser queueReceiver = new Parser();
String message = queueReceiver.subscribe();
System.out.println("Got message from Queue ==> " + message);
}
public String subscribe() throws NamingException, JMSException {
String messageContent = "";
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, QPID_ICF);
properties.put(CF_NAME_PREFIX + CF_NAME,
getTCPConnectionURL(userName, password));
properties.put("topic." + topicName, topicName);
System.out.println("getTCPConnectionURL(userName,password) = "
+ getTCPConnectionURL(userName, password));
InitialContext ctx = new InitialContext(properties);
// Lookup connection factory
TopicConnectionFactory connFactory = (TopicConnectionFactory) ctx
.lookup(CF_NAME);
TopicConnection topicConnection = connFactory.createTopicConnection();
topicConnection.start();
TopicSession topicSession = topicConnection.createTopicSession(false,
QueueSession.AUTO_ACKNOWLEDGE);
// Send message
// Topic topic = topicSession.createTopic(topicName);
Topic topic = (Topic) ctx.lookup(topicName);
javax.jms.TopicSubscriber topicSubscriber = topicSession
.createDurableSubscriber(topic,"topicQueue");
Message message = topicSubscriber.receive();
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
System.out.println("textMessage.getText() = "
+ textMessage.getText());
messageContent = textMessage.getText();
}
topicSubscriber.close();
topicSession.close();
topicConnection.stop();
topicConnection.close();
return messageContent;
}
public String getTCPConnectionURL(String username, String password) {
return new StringBuffer().append("amqp://").append(username)
.append(":").append(password).append("#")
.append(CARBON_CLIENT_ID).append("/")
.append(CARBON_VIRTUAL_HOST_NAME).append("?brokerlist='tcp://")
.append(CARBON_DEFAULT_HOSTNAME).append(":")
.append(CARBON_BROKER_PORT).append("'").toString();
}
}
This is an issue in the MB 2.0.1 distribution with the durable subscribers. The reason for this is when the Parser class first runs, receives a message, and the subscriber is stopped, then when you start the Parser for the second time, it fails to starts the subscription back as the previous 'subscriber' entry is still there, and you will see the following in the terminal.The client will be timed out after few tries which is why you get the error log.
[2013-04-22 12:12:52,617] INFO {org.wso2.andes.server.protocol.AMQProtocolEngine} - Closing channel due to: Cannot subscribe to queue carbon:topicQueue as it already has an existing exclusive consumer
[2013-04-22 12:12:52,621] INFO {org.wso2.andes.server.protocol.AMQProtocolEngine} - Channel[1] awaiting closure - processing close-ok
[2013-04-22 12:12:52,621] INFO {org.wso2.andes.server.handler.ChannelCloseOkHandler} - Received channel-close-ok for channel-id 1
This issue has been fixed in MB 2.1.0 release which is expected to be out in the coming weeks. If you need please try your sample subscriber with MB 2.1.0 - Alpha version from here. This should work fine with that pack.
About unsubscribing from a topic add the following line into your Parser code and run back when you need to unsubscribe.
topicSubscriber.close();
**topicSession.unsubscribe("topicQueue"); // add the name used to identify the subscription in the place of "topicQueue"**
topicSession.close();
topicConnection.stop();
topicConnection.close();

trying to upload video using graph api

I have been trying to implement a video upload facebook feature for my mobile app for a while now but never really succeeded with rest. I learnt yesterday that the graph alternative was available.
After getting a few errors to do with access key mainly i have gotten to the point where output stream succesfully writes the movie file and the input stream just receives an empty json array once i have written the 3gp file.
Anyone any idea why I would get an empty json array and no video gets published when i get all my code to run, i get 200 response code and the server sends me a non error response?
Any help greatly appreciated.
Here is the class that gets the blank json array (send method). I have appended the token to the url and in the table to be sure. I am sorry if the code is untidy buts it just been a day of trial and error.
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import net.rim.device.api.io.http.HttpProtocolConstants;
public class HttpMultipartRequest2
{
static final String BOUNDARY = "----------V2ymHFg03ehbqgZCaKO6jy";
byte[] postBytes = null;
String url = null;
Hashtable paramsTable;
public HttpMultipartRequest2(String url, Hashtable params,
String fileField, String fileName, String fileType, byte[] fileBytes) throws Exception
{
this.url = url;
String boundary = getBoundaryString();
paramsTable = params;
String boundaryMessage = getBoundaryMessage(boundary, params, fileField, fileName, fileType);
String endBoundary = "\r\n--" + boundary + "--\r\n";
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(boundaryMessage.getBytes());
bos.write(fileBytes);
bos.write(endBoundary.getBytes());
this.postBytes = bos.toByteArray();
bos.close();
}
String getBoundaryString() {
return BOUNDARY;
}
String getBoundaryMessage(String boundary, Hashtable params, String fileField, String fileName, String fileType)
{
StringBuffer res = new StringBuffer("--").append(boundary).append("\r\n");
Enumeration keys = params.keys();
while(keys.hasMoreElements())
{
String key = (String)keys.nextElement();
String value = (String)params.get(key);
res.append("Content-Disposition: form-data; name=\"").append(key).append("\"\r\n")
.append("\r\n").append(value).append("\r\n")
.append("--").append(boundary).append("\r\n");
}
res.append("Content-Disposition: form-data; name=\"").append(fileField)
.append("\"; filename=\"").append(fileName).append("\"\r\n")
.append("Content-Type: ").append(fileType).append("\r\n\r\n");
Log.info(("res "+res.toString()));
return res.toString();
}
public String send() throws Exception
{
StringBuffer sb = new StringBuffer();
HttpConnection hc = null;
InputStream is = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] res = null;
try
{
Log.info("before hc open"+ url);
hc = (HttpConnection) Connector.open(url);
hc.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + getBoundaryString());
hc.setRequestProperty("access_token", (String)paramsTable.get("access_token"));
hc.setRequestProperty(HttpProtocolConstants.HEADER_CONTENT_LENGTH, String.valueOf(postBytes.length));
hc.setRequestProperty( "x-rim-transcode-content", "none" );
ByteArrayOutputStream out = new ByteArrayOutputStream();
OutputStream dos = hc.openOutputStream();
is = hc.openInputStream();
Log.info("before dos write responsecode");// + hc.getResponseCode());
out.write(postBytes, 0, postBytes.length);
//Log.info("flushing"+ hc.getResponseCode());
Log.info("after doswrite responsecode");
dos.write(out.toByteArray());
dos.flush();
Log.info("after flush");
if(dos!=null)
dos.close();
int ch;
Log.info("before openinput ");
Log.info("after openinput ");
while ((ch = is.read()) != -1)
{
bos.write(ch);
sb.append((char)ch);
Log.info("char"+(char)ch);
}
res = bos.toByteArray();
Log.info("Response recieved from Server is : " + sb.toString() );
}
catch(Exception e)
{
Log.info(hc.getResponseCode() + "sexce"+e);
}
catch(OutOfMemoryError error)
{
Log.info("outofmemory " + error);
System.gc();
}
finally
{
try
{
if(bos != null)
bos.close();
if(is != null)
is.close();
if(hc != null)
hc.close();
}
catch(Exception e2)
{
Log.info("finally exception"+ e2);
}
}
return sb.toString();
}
}
Are you trying to upload to a user's feed or to a page? There is an Open Bug regarding posting to pages.
Also, could you post some code?
Assuming that you've read the documentation:
Facebook Graph API->Video
And that you are using graph-video.facebook.com, not graph.facebook.com.