I am using SpringBoot for my restful web service and for one of the end points I am sending a ByteArray as response which works perfectly as it uses ByteArrayHttpMessageConverter.
But now I want to send List of ByteArray in response but it fails as it is not able to find suitable Message converter.
Any ideas on how this can be achieved.
Below is snippet of code for End Point. If I return just byte array instead of list then it works but when I try to return list of byte array then it fails as it cannot find Message converter:
#RequestMapping(value = "/payloadList", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<List<byte[]>> loadPayload(#RequestParam(value = "tradeIds", required = false) List<String> tradeIds,
#RequestParam(value = "clientName", required = false) String clientName) throws SQLException, IOException {
LOG.info(String.format("Fetching generic trade details for client : {%s} and trade id : {%s}", clientName, Arrays.toString(tradeIds.toArray())));
tradeIds.forEach(tradeId->validateRequestParams(tradeId, clientName));
List<byte[]> payload = tradeLoadService.loadPayload(clientName,tradeIds);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<List<byte[]>> (payload, headers, HttpStatus.OK);
}
Related
i have this code:
public static String currencyConverter() {
allCurrency test = new allCurrency();
HttpRequest request = new HttpRequest();
HttpResponse response = new HttpResponse();
Http http = new Http();
request.setEndpoint(endPoint);
request.setMethod('GET');
response = http.send(request);
String JSONresponse = response.getBody();
currencyJSON currencyJSON = (currencyJSON)JSON.deserialize(JSONresponse, currencyJSON.class);
test.USD = currencyJSON.rates.USD;
test.CAD = currencyJSON.rates.CAD;
test.EUR = currencyJSON.rates.EUR;
test.GBP = currencyJSON.rates.GBP;
Log__c logObject = new Log__c();
logObject.Status_Code__c = String.valueOf(response.getStatusCode());
logObject.Response_Body__c = response.getBody();
insert logObject;
if (response.getStatusCode() == 200) {
Exchange_Rate__c ExchangeRateObject = new Exchange_Rate__c();
ExchangeRateObject.CAD__c = currencyJSON.rates.CAD;
ExchangeRateObject.EUR__c = currencyJSON.rates.EUR;
ExchangeRateObject.GBP__c = currencyJSON.rates.GBP;
ExchangeRateObject.USD__c = currencyJSON.rates.USD;
ExchangeRateObject.Log__c = logObject.id;
insert ExchangeRateObject;
}
return JSON.serialize(test);
}
Here I am getting different currencies and then calling them in LWC and also I create two objects with values.
I want these objects to be created every day at 12PM.
Tell me how to implement this through the apex scheduler.
You need a class that implements Schedulable. Can be this class, just add that to the header and add execute method. Or can be separate class, doesn't matter much.
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_scheduler.htm
Something like
public with sharing MyClass implements Schedulable{
public static String currencyConverter() { ... your method here }
public void execute(SchedulableContext sc) {
currencyConverter();
}
}
Once your class saves OK you should be able to schedule it from UI (Setup -> Apex Classes -> button) or with System.schedule 1-liner from Developer Console for example.
Alternative would be to have a scheduled Flow - but that's bit more work with making your Apex callable from Flow.
P.S. Don't name your variables test. Eventually some time later you may need "real" stuff like Test.isRunningTest() and that will be "fun". It's like writing
Integer Account = 5; // happy debugging suckers
I am implementing AppEngine server as a backend for my Android application. I use Datastore, I query it via Objectify service and I use Endpoints that I call via URL.
I have an entity User with properties like this:
#Id
Long id;
/**
* Name or nickname of the user
*/
public String name;
#Index
public String email;
#JsonIgnore
List<Key<User>> friends;
public User()
{
devices = new ArrayList<String>();
friendsWithKey = new ArrayList<Key<User>>();
}
public static User findRecordById(Long id)
{
return ofy().load().type(User.class).id(id).now();
}
#ApiMethod(name = "friends", httpMethod = "GET", path = "users/{userId}/friends")
public JSONObject getFriends(#Named("userId") String userId)
{
User user = User.findRecordById(Long.parseLong(userId));
JSONObject friendsObject = new JSONObject();
JSONArray jsonArray = new JSONArray();
JSONObject friend;
List<User> userList = new ArrayList<User>();
if (user.friendsWithKey != null)
{
for (Key<User> id : user.friendsWithKey)
{
friend = new JSONObject();
User user1 = User.findRecordById(id.getId());
userList.add(user1);
friend.put("name", user1.name);
friend.put("email", user1.email);
friend.put("id", user1.id);user1.lastTimeOnline.getTime());
jsonArray.add(friend);
}
friendsObject.put("friends", jsonArray);
}
return friendsObject;
}
It sometimes returns only a subset of friends. It is weird and I do not get where I could go wrong. If I get the User object from the DB, it already has a wrong List of Key values. But if I look into the database via console, I can see all of the users that ahve been added as friends.
I reaally need to fix this bug. Please, help.
It is very strange because it only happens once in a while and is non-deterministic in every way.
Now I'm trying to convert Java List object to JSON array, and struggling to convert UTF-8 strings. I've tried all followings, but none of them works.
Settings.
response.setContentType("application/json");
PrintWriter out = response.getWriter();
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
final ObjectMapper mapper = new ObjectMapper();
Test#1.
// Using writeValueAsString
String json = ow.writeValueAsString(list2);
Test#2.
// Using Bytes
final byte[] data = mapper.writeValueAsBytes(list2);
String json = new String(data, "UTF-8");
Test#3.
// Using ByteArrayOutputStream with new String()
final OutputStream os = new ByteArrayOutputStream();
mapper.writeValue(os, list2);
final byte[] data = ((ByteArrayOutputStream) os).toByteArray();
String json = new String(data, "UTF-8");
Test#4.
// Using ByteArrayOutputStream
final OutputStream os = new ByteArrayOutputStream();
mapper.writeValue(os, list2);
String json = ((ByteArrayOutputStream) os).toString("UTF-8");
Test#5.
// Using writeValueAsString
String json = mapper.writeValueAsString(list2);
Test#6.
// Using writeValue
mapper.writeValue(out, list2);
Like I said, none of above works. All displays characters like "???". I appreciate your helps. I'm using Servlet to send JSON response to clients.
This problem only happens when I write java.util.List object. If I write single data object, e.g. customer object in below example, then there is no ??? characters, and UTF-8 is working with the following code.
PrintWriter out = response.getWriter();
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(customer);
out.print(json);
The answer was very simple. You need to specify UTF-8 charset encoding in response.setContentType too.
response.setContentType("application/json;charset=UTF-8");
Then, many of above code will work correctly. I will leave my question as is, since it will show you several ways of writing JSON to clients.
On RequestMapping in Controller:
#RequestMapping(value = "/user/get/sth",
method = RequestMethod.GET,
produces = { "application/json;**charset=UTF-8**" })
I am trying to use resteasy. While I am able to do send a mixed multipart as a request to a webservice, I am unable to do get a mixed multipart in the response.
For eg: Requesting for a file (byte[] or stream) and the file name in a single Response.
Following is what I have tested:
Service code:
#Path("/myfiles")
public class MyMultiPartWebService {
#POST
#Path("/filedetail")
#Consumes("multipart/form-data")
#Produces("multipart/mixed")
public MultipartOutput fileDetail(MultipartFormDataInput input) throws IOException {
MultipartOutput multipartOutput = new MultipartOutput();
//some logic based on input to locate a file(s)
File myFile = new File("samplefile.pdf");
multipartOutput.addPart("fileName:"+ myFile.getName(), MediaType.TEXT_PLAIN_TYPE);
multipartOutput.addPart(file, MediaType.APPLICATION_OCTET_STREAM_TYPE);
return multipartOutput;
}
}
Client code:
public void getFileDetails(/*input params*/){
HttpClient client = new DefaultHttpClient();
HttpPost postRequest = new HttpPost("urlString");
MultipartEntity multiPartEntity = new MultipartEntity();
//prepare the request details
postRequest.setEntity(multiPartEntity);
HttpResponse response = client.execute(postRequest);
HttpEntity returnEntity = response.getEntity();
//extracting data from the response
Header header = returnEntity.getContentType();
InputStream is = returnEntity.getContent();
if (is != null) {
byte[] bytes = IOUtils.toByteArray(is);
//Can we see the 2 parts that were added?
//Able to get a single InputStream only, and hence unable to differentiate two objects in the response
//Trying to see the contents - printing as string
System.out.println("Output from Response :: " + new String(bytes));
}
}
The output is as follows - able to see 2 different objects with different content types, but unable to extract them separately.
Output from Response ::
--af481055-4e4f-4860-9c0b-bb636d86d639
Content-Type: text/plain
fileName: samplefile.pdf
--af481055-4e4f-4860-9c0b-bb636d86d639
Content-Length: 1928
Content-Type: application/octet-stream
%PDF-1.4
<<pdf content printed as junk chars>>
How can I extract the 2 objects from the response?
UPDATE:
Tried the following approach to extract the different parts - use the 'boundary' to break the MultipartStream; use the content type string to extract approp object.
private void getResponeObject(HttpResponse response) throws IllegalStateException, IOException {
HttpEntity returnEntity = response.getEntity();
Header header = returnEntity.getContentType();
String boundary = header.getValue();
boundary = boundary.substring("multipart/mixed; boundary=".length(), boundary.length());
System.out.println("Boundary" + boundary); // --af481055-4e4f-4860-9c0b-bb636d86d639
InputStream is = returnEntity.getContent();
splitter(is, boundary);
}
//extract subsets from the input stream based on content type
private void splitter(InputStream is, String boundary) throws IOException {
ByteArrayOutputStream boas = null;
FileOutputStream fos = null;
MultipartStream multipartStream = new MultipartStream(is, boundary.getBytes());
boolean nextPart = multipartStream.skipPreamble();
System.out.println("NEXT PART :: " + nextPart);
while (nextPart) {
String header = multipartStream.readHeaders();
if (header.contains("Content-Type: "+MediaType.APPLICATION_OCTET_STREAM_TYPE)) {
fos = new FileOutputStream(new File("myfilename.pdf"));
multipartStream.readBodyData(fos);
} else if (header.contains("Content-Type: "+MediaType.TEXT_PLAIN_TYPE)) {
boas = new ByteArrayOutputStream();
multipartStream.readBodyData(boas);
String newString = new String( boas.toByteArray());
} else if (header.contains("Content-Type: "+ MediaType.APPLICATION_JSON_TYPE)) {
//extract string and create JSONObject from it
} else if (header.contains("Content-Type: "+MediaType.APPLICATION_XML_TYPE)) {
//extract string and create XML object from it
}
nextPart = multipartStream.readBoundary();
}
}
Is this the right approach?
UPDATE 2:
The logic above seems to work. But got another block, when receiving the RESPONSE from the webservice. I could not find any references to handle such issues in the Response.
The logic assumes that there is ONE part for a part type. If there are, say, 2 JSON parts in the response, it would be difficult to identify which part is what. In other words, though we can add the part with a key name while creating the response, we are unable to extract the key names int he client side.
Any clues?
You can try the following approach...
At the server side...
Create a wrapper object that can encapsulate all types. For eg., it could have a Map for TEXT and another Map for Binary data.
Convert the TEXT content to bytes (octet stream).
Create a MetaData which contains references to the Key names and their type. Eg., STR_MYKEY1, BYTES_MYKEY2. This metadata can also be converted into octet stream.
Add the metadata and the wrapped entity as parts to the multipart response.
At the Client side...
Read the MetaData to get the key names.
Use the key name to interpret each part. Since the Keyname from the metadata tells if the original data is a TEXT or BINARY, you should be able to extract the actual content with appropriate logic.
The same approach can be used for upstream, from client to service.
On top of this, you can compress the TEXT data which will help in reducing the content size...
public void Register(string email, string name, string hash)
{
string registerData = "{\"email\":\"" + email + "\",\"name\":\"" + name + "\",\"hash\":\"" + hash + "\"}";
WebClient webClient = new WebClient();
webClient.Headers["Content-Type"] = "application/json";
webClient.UploadStringCompleted += new UploadStringCompletedEventHandler(HandleRegisterAsyncResult);
webClient.UploadStringAsync(new Uri(registerUrl), registerData);
}
void HandleRegisterAsyncResult(object sender, UploadStringCompletedEventArgs e)
{
}
I'm basically trying to call a webservice with a https:// post command that takes a data string. It works well, except when I get an error I can't seem to find the actual WebResponse content. If I cast the e.Error that was returned to a WebException there's a class called Response that's a BrowserHttpWebResponse but the ContentLength is 0 (eventhough I can see the content lenght is not 0 in fiddler)
Is there a way to get the response content with this method? And if not is there another way to do a Post command that does allow me to get the response content?