How to pass a value from a synchronous method to asynchronous method within an apex class? - rest

I have made a REST call to a url and need to pass the jsonresponse obtained from the synchronous method to the below asynchronous method.I have used a static variable - strresponse to do the same.But i am getting a null value when i call this value in the asynchronous method.Could this be because asynchronous methods do not remember the value given by a synchronous method? is there any alternate way this could be done?
code below:
public with sharing class myController {
public Static String strResponse ;
#AuraEnabled
public static Map<String, Object> retriveNews(){
HttpRequest httpRequest = new HttpRequest();
httpRequest.setEndpoint('endpoint URL');
httpRequest.setMethod('GET');
try{
Http http = new Http();
HttpResponse httpResponse = http.send(httpRequest);
if(httpResponse.getStatusCode() == 200){
newsController.strResponse = httpResponse.getBody();
} else {
throw new CalloutException(httpResponse.getBody());
}
} catch(Exception ex){
throw ex;
}
Map<String, Object> newsJsonData = new Map<String, Object>();
if(!String.isBlank(newsController.strResponse)){
System.debug('jsonstring:'+newsController.strResponse);
newsJsonData = (Map<String, Object>)JSON.deserializeUntyped(newsController.strResponse);
}
System.debug('jsonstring in retrivenews:'+newsController.strResponse);
if(!newsJsonData.isEmpty()){
return newsJsonData;
} else {
return null;
}
}
#future(callout=true)
public static void insertnews()
{
List<Newsroom__c> nrmlist = new List<Newsroom__c>();
System.debug('jsonstring in insertnews:'+newsController.strResponse);
JSONParser parser = JSON.createParser(newsController.strResponse);
while (parser.nextToken() != null) {
// Start at the array of invoices.
if (parser.getCurrentToken() == JSONToken.START_ARRAY) {
while (parser.nextToken() != null) {
// Advance to the start object marker to
// find next invoice statement object.
if (parser.getCurrentToken() == JSONToken.START_OBJECT) {
objectne nrm = (objectne)parser.readValueAs(objectne.class);
objectne__c nroom = new objectne__c(Author__c = nrm.Author,Description__c = nrm.Description);
String s = JSON.serialize(nrm);
system.debug('Serialized object: ' + s);
nrmlist.add(nroom);
system.debug('list of nrooms:'+ nrmlist);
}
}
}
}
Database.SaveResult[] lsr = Database.insert(nrmlist, false) ;
System.debug(lsr);
}
Error - when newscontroller.insertnews() is called - null string to parser

Related

System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification calling Autorest generated code

I have a unit test, calling a service that makes use of Autorest generated code to call my Api.
I want my unit test to display the error that my Api is throwing, but there seems to be an error in the service's error handling.
I am using the following command to generate code to consume my api.
autorest --input-file=https://mywebsite.com.au:4433/myapi/api-docs/v1/swagger.json --output-folder=generated --csharp --namespace=MyConnector
The generated "client code" contains
/// <param name='request'>
/// </param>
/// <param name='customHeaders'>
/// Headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
/// <exception cref="HttpOperationException">
/// Thrown when the operation returned an invalid status code
/// </exception>
/// <exception cref="SerializationException">
/// Thrown when unable to deserialize the response
/// </exception>
/// <return>
/// A response object containing the response body and response headers.
/// </return>
public async Task<HttpOperationResponse<GetAvailableCarriersResponse>> GetAvailableCarriersByJobHeaderIdWithHttpMessagesAsync(GetAvailableCarriersRequest request = default(GetAvailableCarriersRequest), Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken))
{
// Tracing
bool _shouldTrace = ServiceClientTracing.IsEnabled;
string _invocationId = null;
if (_shouldTrace)
{
_invocationId = ServiceClientTracing.NextInvocationId.ToString();
Dictionary<string, object> tracingParameters = new Dictionary<string, object>();
tracingParameters.Add("request", request);
tracingParameters.Add("cancellationToken", cancellationToken);
ServiceClientTracing.Enter(_invocationId, this, "GetAvailableCarriersByJobHeaderId", tracingParameters);
}
// Construct URL
var _baseUrl = BaseUri.AbsoluteUri;
var _url = new System.Uri(new System.Uri(_baseUrl + (_baseUrl.EndsWith("/") ? "" : "/")), "api/shipping-management/Get-Available-Carriers").ToString();
// Create HTTP transport objects
var _httpRequest = new HttpRequestMessage();
HttpResponseMessage _httpResponse = null;
_httpRequest.Method = new HttpMethod("POST");
_httpRequest.RequestUri = new System.Uri(_url);
// Set Headers
if (customHeaders != null)
{
foreach(var _header in customHeaders)
{
if (_httpRequest.Headers.Contains(_header.Key))
{
_httpRequest.Headers.Remove(_header.Key);
}
_httpRequest.Headers.TryAddWithoutValidation(_header.Key, _header.Value);
}
}
// Serialize Request
string _requestContent = null;
if(request != null)
{
_requestContent = SafeJsonConvert.SerializeObject(request, SerializationSettings);
_httpRequest.Content = new StringContent(_requestContent, System.Text.Encoding.UTF8);
_httpRequest.Content.Headers.ContentType =System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json-patch+json; charset=utf-8");
}
// Send Request
if (_shouldTrace)
{
ServiceClientTracing.SendRequest(_invocationId, _httpRequest);
}
cancellationToken.ThrowIfCancellationRequested();
_httpResponse = await HttpClient.SendAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
if (_shouldTrace)
{
ServiceClientTracing.ReceiveResponse(_invocationId, _httpResponse);
}
HttpStatusCode _statusCode = _httpResponse.StatusCode;
cancellationToken.ThrowIfCancellationRequested();
string _responseContent = null;
if ((int)_statusCode != 200)
{
var ex = new HttpOperationException(string.Format("Operation returned an invalid status code '{0}'", _statusCode));
if (_httpResponse.Content != null) {
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
}
else {
_responseContent = string.Empty;
}
ex.Request = new HttpRequestMessageWrapper(_httpRequest, _requestContent);
ex.Response = new HttpResponseMessageWrapper(_httpResponse, _responseContent);
if (_shouldTrace)
{
ServiceClientTracing.Error(_invocationId, ex);
}
_httpRequest.Dispose();
if (_httpResponse != null)
{
_httpResponse.Dispose();
}
throw ex;
}
// Create Result
var _result = new HttpOperationResponse<GetAvailableCarriersResponse>();
_result.Request = _httpRequest;
_result.Response = _httpResponse;
// Deserialize Response
if ((int)_statusCode == 200)
{
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
_result.Body = SafeJsonConvert.DeserializeObject<GetAvailableCarriersResponse>(_responseContent, DeserializationSettings);
}
catch (JsonException ex)
{
_httpRequest.Dispose();
if (_httpResponse != null)
{
_httpResponse.Dispose();
}
throw new SerializationException("Unable to deserialize the response.", _responseContent, ex);
}
}
if (_shouldTrace)
{
ServiceClientTracing.Exit(_invocationId, _result);
}
return _result;
}
I have a unit test to call the generated code using
var api = MakeApi();
var task=api.GetAvailableCarriersByJobHeaderIdWithHttpMessagesAsync(req);
var carriers = task.Result.Body.Carriers;
where
private static MyApiService MakeApi()
{
var setting = new MyAPISettings(false);
var api = new MyApiService(setting);
return api;
}
and MyApiService contains (with altered namespaces)
public Task<HttpOperationResponse<GetAvailableCarriersResponse>> GetAvailableCarriersByJobHeaderIdWithHttpMessagesAsync(
GetAvailableCarriersRequest request = default(GetAvailableCarriersRequest), Dictionary<string, List<string>> customHeaders = null,
CancellationToken cancellationToken = default(CancellationToken))
{
return ApiCaller.ExecuteAsync(
async headers => await API.GetAvailableCarriersByJobHeaderIdWithHttpMessagesAsync(request, headers, cancellationToken),
async () => await GetTokenHeadersAsync(customHeaders));
}
where apicaller is
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MyServices
{
public static class ApiCaller
{
private static Dictionary<string, List<string>> Headers { get; set; }
private static string GetHeadersMessage()
{
string ret = "";
if (Headers != null)
{
foreach (string key in Headers.Keys)
{
if (Headers[key] != null)
{
foreach (string value in Headers[key])
{
ret = $"{key}-{value}\n";
}
}
}
}
return ret;
}
public async static Task<T> ExecuteAsync<T>(Func<Dictionary<string, List<string>>, Task<T>> f,
Func<Task<Dictionary<string, List<string>>>> getHeaders)
{
T ret = default(T);
try
{
try
{
if (getHeaders != null && Headers == null)
{
Headers = await getHeaders();
}
ret = await f(Headers);
}
catch (Microsoft.Rest.HttpOperationException ex1)
{
if (ex1.Response?.StatusCode == System.Net.HttpStatusCode.Unauthorized && getHeaders != null)
{
Headers = await getHeaders();
ret = await f(Headers);
}
else
{
throw;
}
}
}
catch (Exception ex)
{
//Log.Error(ex, $"... API CALL ERROR ...\nHEADERS:{GetHeadersMessage()}");
throw new Exception($"Error calling the API. {ex.Message}", ex);
}
return ret;
}
}
}
My Api throws an InternalServerError
However when I run the unit test, I get an error in the client code.
The error occurs at
// Create Result
var _result = new HttpOperationResponse<GetAvailableCarriersResponse>();
And is
System.Exception: Error calling the API. Operation returned an invalid status code 'InternalServerError' ---> Microsoft.Rest.HttpOperationException: Operation returned an invalid status code 'InternalServerError'
at MyConnector.MyApi.<GetAvailableCarriersByJobHeaderIdWithHttpMessagesAsync>d__49.MoveNext()
How can I work around this?
I note that the code for HttpOperationResponse is
namespace Microsoft.Rest
{
/// <summary>
/// Represents the base return type of all ServiceClient REST operations.
/// </summary>
public class HttpOperationResponse<T> : HttpOperationResponse, IHttpOperationResponse<T>, IHttpOperationResponse
{
/// <summary>Gets or sets the response object.</summary>
public T Body { get; set; }
}
}
Here is the structure for GetAvailableCarriersResponse
using Newtonsoft.Json;
using System.Collections.Generic;
public partial class GetAvailableCarriersResponse
{
public GetAvailableCarriersResponse()
{
CustomInit();
}
public GetAvailableCarriersResponse(IList<DeliverBy> carriers = default(IList<DeliverBy>))
{
Carriers = carriers;
CustomInit();
}
partial void CustomInit();
[JsonProperty(PropertyName = "carriers")]
public IList<DeliverBy> Carriers { get; set; }
}
[Update]
In ApiCaller ExecuteAsync the following executes.
throw;
If I catch the error at this point, it's (edited) ToString() returns
"Microsoft.Rest.HttpOperationException: Operation returned an invalid status code 'InternalServerError' at MyAPI.
<GetAvailableCarriersByJobHeaderIdWithHttpMessagesAsync>d__49.MoveNext() in
MyConnector\\generated\\MyAPI.cs:line 4018
End of stack trace from previous location where exception was thrown at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at
System.Runtime.CompilerServices.TaskAwaiter.
HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at MyApiService.<>c__DisplayClass39_0.<<GetAvailableCarriersByJobHeaderIdWithHttpMessagesAsync>b__0>d.MoveNext()
in MyApiService.cs:line 339
End of stack trace from previous location where exception was thrown
at System.Runtime.ExceptionServices.ExceptionDispatch
Info.Throw() at System.Runtime.CompilerServices.TaskAwaiter.
HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at MyServices.ApiCaller.<ExecuteAsync>d__5`1.MoveNext()
in ApiCaller.cs:line 50"
I edited some of the names in the above code to simplify and obfuscate.
[Update]
The problem seems to be to do with the getHeaders parameter to ApiCaller.ExecuteAsync
[Update]
If I examine ex1 thrown in ExecuteAsync, I can get my Api Error type using
ex1.Response.StatusCode
but how do I get the error description?
What I did to get error description is to cast it to one of the error types generated by Autorest.
if (myRawResponseObject is My422Response my422Response)
{
// Response has HTTP Status Code 422
Console.WriteLine($"Error Response Type: {my422Response.ToString()}");
}
If you OpenAPI document defines error properties for a 422 response, then you will find them on the My422Response object.

Integration of Market place with Integration bus in websphere

We have a requirement as below
Integration System needs to call our service
Our service needs to call FlipKart service appending the token in the request
Get the response back to Integration system
The above should work seamlessly for both GET and PUT requests.
I had developed a REST-project in eclipse and was able to get the GET and PUT response back to Integration.
However have few problems
In Get Requests, we are explicitly setting the headers and produces annotation to appication/json. How do we set it for all kind of requests?
In Post Response, we do not get the entire response and we are not able to set the application type in the response (Not sure how!)
All these requests are failing if the application type is pdf, img etc.
Can someone please help on the same?
Code implemented so far:
#GET
#Path("{pathvalue : (.+)?}")
#Produces("{application/json;application/octet-stream}")
public String getFlipKartResponse(#Context UriInfo uriInfo, #PathParam("pathvalue") String pathValue, #Context HttpServletRequest request) throws ClassNotFoundException,IOException {
String methodName = "getFlipKartResponse";
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.entering(CLASSNAME, methodName);
}
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
//if(null == flipkartUrl || flipkartUrl.isEmpty())
flipkartUrl = config.getProperty(ServiceConstants.FLIPKART_URL);
String queryParam = new String();
Iterator<String> iterator = queryParams.keySet().iterator();
while (iterator.hasNext()) {
String parameter = iterator.next();
queryParam = queryParam.concat(parameter + ServiceConstants.EQUALS + queryParams.getFirst(parameter) + ServiceConstants.AMPERSAND);
}
String modifiedflipkartUrl = flipkartUrl.concat(pathValue).concat(ServiceConstants.QUESTION).concat(queryParam);
if (modifiedflipkartUrl.endsWith(ServiceConstants.QUESTION) || modifiedflipkartUrl.endsWith(ServiceConstants.AMPERSAND)) {
modifiedflipkartUrl = modifiedflipkartUrl.substring(0, modifiedflipkartUrl.length()-1);
}
LOGGER.log(Level.INFO, "Flipkart URL framed : "+ modifiedflipkartUrl);
url = new URL(modifiedflipkartUrl);
connection = (HttpsURLConnection) url.openConnection();
setHeadersInConnectionObject(url, connection, request.getMethod());
return handleInvalidToken(connection.getResponseCode(), request);
}
private String handleInvalidToken(int responseCode, HttpServletRequest request){
try {
if (connection.getResponseCode() == 401) {
LOGGER.log(Level.INFO, "ResponseCode " + connection.getResponseCode());
connection.disconnect();
regenerateAccessToken();
connection = (HttpsURLConnection) url.openConnection();
setHeadersInConnectionObject(url, connection, request.getMethod());
inputLine = new BufferedReader(new InputStreamReader(connection.getInputStream()));
} else if (connection.getResponseCode() == 200) {
inputLine = new BufferedReader(new InputStreamReader(connection.getInputStream()));
} else {
inputLine = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
}
String responseInputLine;
String responseMessage = "";
while (null != (responseInputLine = inputLine.readLine())) {
responseMessage = responseMessage + responseInputLine;
}
inputLine.close();
connection.disconnect();
return responseMessage;
} catch (Exception e) {
LOGGER.log(Level.SEVERE,"Exception occured while calling service.Please try again after sometime : ", e);
return this.handleErrorResponse("Exception occured while calling service.Please try again after sometime.");
}
}
private void regenerateAccessToken() throws ClassNotFoundException, IOException, SQLException{
TokenGenerator tokenGenerator = new TokenGenerator();
accessToken= tokenGenerator.getAccessToken();
}
#POST
#Path("{pathvalue : (.+)?}")
#Produces({"application/json;application/octet-stream"})
public String getFlipKartPostResponse(#Context UriInfo uriInfo, #PathParam("pathvalue") String pathValue,#Context HttpServletRequest requestBody) throws ClassNotFoundException,IOException, SQLException {
String methodName = "getFlipKartPostResponse";
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.entering(CLASSNAME, methodName);
}
//if(null == flipkartUrl || flipkartUrl.isEmpty())
flipkartUrl = config.getProperty(ServiceConstants.FLIPKART_URL);
String modifiedflipkartUrl = flipkartUrl + pathValue;
url = new URL(modifiedflipkartUrl);
LOGGER.log(Level.INFO, "Flipkart URL framed : "+ flipkartUrl);
connection = (HttpsURLConnection) url.openConnection();
setHeadersInConnectionObject(url, connection, requestBody.getMethod());
InputStream requestInputStream = requestBody.getInputStream();
String reqBody = getStringFromInputStream(requestBody.getInputStream());
OutputStream outputStream = connection.getOutputStream();
outputStream.write(reqBody.getBytes());
outputStream.flush();
if(connection.getResponseCode() == 401) {
connection.disconnect();
regenerateAccessToken();
connection = (HttpsURLConnection) url.openConnection();
setHeadersInConnectionObject(url, connection, requestBody.getMethod());
outputStream = connection.getOutputStream();
outputStream.write(reqBody.getBytes());
outputStream.flush();
}
String output = getStringFromInputStream (connection.getInputStream());
connection.disconnect();
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.exiting(CLASSNAME, methodName);
}
return output;
}
private static String getStringFromInputStream(InputStream is) {
String methodName = "getStringFromInputStream";
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.entering(CLASSNAME, methodName);
}
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try {
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.exiting(CLASSNAME, methodName);
}
return sb.toString();
}
/**
* Method to generate the access token
* #return String - Access token
* #throws IOException
*/
private String getAccessToken() throws IOException {
if (null != accessToken) {
return accessToken;
} else {
url = getClass().getResource(ServiceConstants.ACCESS_TOKEN_CONFIG_PATH);
file = new File(url.getPath());
reader = new BufferedReader (new InputStreamReader (new FileInputStream (file), ServiceConstants.UTF_ENCODING));
accessToken = reader.readLine();
reader.close();
return accessToken;
}
}
/**
* Method to construct error response for exception scenario
* #param errorMessage
* #return
*/
private String handleErrorResponse(String errorMessage) {
String methodName = "handleErrorResponse";
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.entering(CLASSNAME, methodName);
}
JSONObject errorResponse = new JSONObject();
JSONArray errorMsg = new JSONArray();
errorResponse.put(ServiceConstants.STATUS, ServiceConstants.STATUS_FAILED);
errorResponse.put(ServiceConstants.ERROR_MESSAGE, errorMessage);
errorMsg.add(errorResponse);
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.exiting(CLASSNAME, methodName);
}
return errorResponse.toString();
}
/**
* Method to form the connection object
* #param url
* #param connection
* #param requestType
* #throws IOException
*/
private void setHeadersInConnectionObject(URL url, HttpsURLConnection connection, String requestType) throws IOException {
String methodName = "setHeadersInConnectionObject";
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.entering(CLASSNAME, methodName);
}
if (null == accessToken) {
getAccessToken();
}
connection.setRequestMethod(requestType);
connection.setRequestProperty(ServiceConstants.AUTHORIZATION, ServiceConstants.BEARER + accessToken);
connection.setDoOutput(true);
if (requestType.equals(ServiceConstants.REQUEST_TYPE_GET)) {
connection.setRequestProperty(ServiceConstants.ACCEPT_HEADER, ServiceConstants.ACCEPT_ALL);
//connection.setRequestProperty(ServiceConstants.ACCEPT_HEADER, ServiceConstants.APPLICATION_JSON);
}
if (requestType.equals(ServiceConstants.REQUEST_TYPE_POST)) {
connection.setRequestProperty(ServiceConstants.ACCEPT_HEADER, ServiceConstants.APPLICATION_JSON);
connection.setRequestProperty(ServiceConstants.CONTENT_TYPE_HEADER, ServiceConstants.APPLICATION_JSON);
//connection.setDoInput(true);
}
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.exiting(CLASSNAME, methodName);
}
}

How to upload empty file with Retrofit 2?

I successfully set up an uploading images to my REST API via retrofit with this code:
File imageFile = ImagePicker.getFileFromResult(this, resultCode, data);
RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"), imageFile);
MultipartBody.Part body =
MultipartBody.Part.createFormData("userpic", imageFile.getName(), requestFile);
RetrofitClient.compositeSubscription.add(RetrofitClient.getService().updateProfileUserpic("Token " + RevolutionApp.getInstance().getUserToken(), body).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Profile>() {
#Override
public void onCompleted() { }
#Override
public void onError(Throwable e) { }
#Override
public void onNext(Profile profile) {
mProfileFragment.fetchProfileData();
}
}));
Now I need to send empty file (null) to my my API. How to implement it?
MultipartBody.Part.createFormData("userpic", imageFile.getName(), requestFile)
does not work
i don't Know this is the right way to do this,i tried like this.its working
MultipartBody.Part fileToUpload = null;
if (realPath != null) {
try {
File file = new File(realPath);
if (file.exists()) {
RequestBody requestBody = RequestBody.create(MediaType.parse("*/*"), file);
fileToUpload = MultipartBody.Part.createFormData("attachment", file.getName(), requestBody);
}
} catch (NullPointerException e) {
e.printStackTrace();
}
}else{
RequestBody attachmentEmpty = RequestBody.create(MediaType.parse("text/plain"), "");
fileToUpload = MultipartBody.Part.createFormData("attachment", "", attachmentEmpty);
}
Note: File Name should not be null ,in place of null use empty("").
Here is final solution:
API interface method to update model:
public void updateProfileData(ProfilePost profile, final OnProfileUpdatedListener listener) {
Observable<Profile> observable;
if (profile.getUserpicPart() != null) {
observable = RetrofitClient.getService().updateProfileData(profile.asHashMap(), profile.getUserpicPart());
} else {
observable = RetrofitClient.getService().updateProfileData(profile.asHashMap());
}
RetrofitClient.compositeSubscription.add(observable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Profile>() {
...
}));
}
Retrofit method signature:
#PUT("/api/v1/profile/")
#Multipart
Observable<Profile> updateProfileData(#Header("Authorization") String authorization, #PartMap() Map<String, RequestBody> partMap, #Part MultipartBody.Part image);
#PUT("/api/v1/profile/")
#Multipart
Observable<Profile> updateProfileData(#Header("Authorization") String authorization, #PartMap() Map<String, RequestBody> partMap);
and model to post:
public class ProfilePost {
MultipartBody.Part userpicPart;
public HashMap<String, RequestBody> asHashMap() {
HashMap<String, RequestBody> result = new HashMap<>();
result.put("first_name", RequestBody.create(MediaType.parse("text/plain"), this.firstName));
result.put("last_name", RequestBody.create(MediaType.parse("text/plain"), this.lastName));
result.put("email", RequestBody.create(MediaType.parse("text/plain"), this.email));
}
public void getUserpicPart() {
if (this.userpicFile == null) {
return null;
}
return MultipartBody.Part.createFormData("userpic", this.userpicFile.getName(), requestFile);
}
}

Sling Forward with SyntheticResource

I'm trying to build a Sling servlet that returns a modified value of a resource from the JCR. I dont want to change the original resource, so I create a SyntheticResource and make my manipulations. I then return it back using the RequestDispatcher.
The following code doesn't return the Modified content as expected and I don't see any errors in the log either. Can you tell me what I'm doing wrong here
#SlingServlet(methods = "GET", resourceTypes = "sling/components/test", selectors = "test")
public class TestServlet extends SlingSafeMethodsServlet {
/**
*
*/
private static final long serialVersionUID = 4078524820231933974L;
private final Logger log = LoggerFactory.getLogger(getClass());
#Reference
ResourceResolverFactory resolverFactory;
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
Map<String, Object> param = new HashMap<String, Object>();
ResourceResolver resolver = null;
response.setContentType("text/html");
StringWriterResponse writerResponse = new StringWriterResponse(response);
PrintWriter writer = response.getWriter();
try {
param.put(ResourceResolverFactory.SUBSERVICE, "testService");
final String path = request.getRequestPathInfo().getResourcePath();
resolver = resolverFactory.getServiceResourceResolver(param);
final Resource resource = resolver.getResource(path);
String resourceType = resource.getResourceType();
Resource testResource = new SyntheticResource(resolver,
path, resourceType) {
public <T> T adaptTo(Class<T> type) {
if (type == ValueMap.class) {
ModifiableValueMap map = resource
.adaptTo(ModifiableValueMap.class);
map.put("jcr:title", "Modified Title");
return (T)map;
}
return super.adaptTo(type);
}
};
RequestDispatcherOptions requestDispatcherOptions = new RequestDispatcherOptions();
requestDispatcherOptions.setReplaceSelectors("");
final RequestDispatcher requestDispatcher = request.getRequestDispatcher(testResource, requestDispatcherOptions);
requestDispatcher.forward(request, writerResponse);
// log.debug( writerResponse.getString() );
writer.println(writerResponse.getString());
response.setStatus(HttpServletResponse.SC_OK );
} catch (Exception e) {
log.error("Exception: ", e);
} finally {
if( resolver != null) {
resolver.close();
}
if( writer != null ){
writer.close();
}
if (writerResponse != null) {
writerResponse.clearWriter();
}
}
}
}
Using a ResourceDecorator would be simpler, it can return a ResourceWrapper that implements the required changes. Just be careful to keep the decorator's decorate method efficient when it's called for a Resource that it doesn't want to decorate, as it will be called for all Resources.

What am I supposed to use in place of "Plugin" for Phonegap 2.9?

I am trying to implement the WebIntent plugin for Phonegap as part of my Android app.
I have downloaded the latest version of WebIntent, within this week, and it has not been updated for about half a year, so I think it is as up to date as possible. I am using version 2.9 of Phonegap.
WebIntent is not working for me, and in my Eclipse interface, it says that the class "Plugin" is deprecated:
This answer here on Stack Overflow indicates that I should use "CordovaPlugin" instead, but Eclipse seems to like that even less:
I'm not sure if this is the reason WebIntent is failing for me, but it looks to be a very likely suspect. What do I do to clear this file of any errors?
Also, I don't know if this is related, but there is another line in the code that triggers another "depracated" warning:
So it may be that WebIntent needs some more general fix or something.
In any case, I just want to get WebIntent working. Advice on how to do that, whether it involves fixing this Plugin error or not, would be most appreciated.
Update: I have tried to edit the code using "CordovaPlugin", but I am still getting errors.
The lines I am getting errors on are:
... and:
This is the whole file:
package com.borismus.webintent;
import java.util.HashMap;
import java.util.Map;
import org.apache.cordova.DroidGap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.text.Html;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;
import org.apache.cordova.api.CallbackContext;
/**
* WebIntent is a PhoneGap plugin that bridges Android intents and web
* applications:
*
* 1. web apps can spawn intents that call native Android applications. 2.
* (after setting up correct intent filters for PhoneGap applications), Android
* intents can be handled by PhoneGap web applications.
*
* #author boris#borismus.com
*
*/
public class WebIntent extends CordovaPlugin {
private String onNewIntentCallback = null;
/**
* Executes the request and returns PluginResult.
*
* #param action
* The action to execute.
* #param args
* JSONArray of arguments for the plugin.
* #param callbackContext
* The callbackContext used when calling back into JavaScript.
* #return boolean
*/
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
try {
if (action.equals("startActivity")) {
if (args.length() != 1) {
PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
callbackContext.sendPluginResult(res);
return false;
}
// Parse the arguments
JSONObject obj = args.getJSONObject(0);
String type = obj.has("type") ? obj.getString("type") : null;
Uri uri = obj.has("url") ? Uri.parse(obj.getString("url")) : null;
JSONObject extras = obj.has("extras") ? obj.getJSONObject("extras") : null;
Map<String, String> extrasMap = new HashMap<String, String>();
// Populate the extras if any exist
if (extras != null) {
JSONArray extraNames = extras.names();
for (int i = 0; i < extraNames.length(); i++) {
String key = extraNames.getString(i);
String value = extras.getString(key);
extrasMap.put(key, value);
}
}
startActivity(obj.getString("action"), uri, type, extrasMap);
callbackContext.success();
return true;
} else if (action.equals("hasExtra")) {
if (args.length() != 1) {
PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
callbackContext.sendPluginResult(res);
return false;
}
Intent i = ((DroidGap)this.cordova.getActivity()).getIntent();
String extraName = args.getString(0);
PluginResult res = new PluginResult(PluginResult.Status.OK, i.hasExtra(extraName));
callbackContext.sendPluginResult(res);
return true;
} else if (action.equals("getExtra")) {
if (args.length() != 1) {
PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
callbackContext.sendPluginResult(res);
return false;
}
Intent i = ((DroidGap)this.cordova.getActivity()).getIntent();
String extraName = args.getString(0);
if (i.hasExtra(extraName)) {
PluginResult res = new PluginResult(PluginResult.Status.OK, i.hasExtra(extraName));
callbackContext.sendPluginResult(res);
return true;
} else {
PluginResult res = new PluginResult(PluginResult.Status.ERROR);
callbackContext.sendPluginResult(res);
return false;
}
} else if (action.equals("getUri")) {
if (args.length() != 0) {
PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
callbackContext.sendPluginResult(res);
return false;
}
Intent i = ((DroidGap)this.cordova.getActivity()).getIntent();
String uri = i.getDataString();
callbackContext.success(uri);
return true;
} else if (action.equals("onNewIntent")) {
if (args.length() != 0) {
PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
callbackContext.sendPluginResult(res);
return false;
}
this.onNewIntentCallback = callbackContext;
PluginResult res = new PluginResult(PluginResult.Status.NO_RESULT);
res.setKeepCallback(true);
callbackContext.sendPluginResult(res);
return true;
} else if (action.equals("sendBroadcast"))
{
if (args.length() != 1) {
PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
callbackContext.sendPluginResult(res);
return false;
}
// Parse the arguments
JSONObject obj = args.getJSONObject(0);
JSONObject extras = obj.has("extras") ? obj.getJSONObject("extras") : null;
Map<String, String> extrasMap = new HashMap<String, String>();
// Populate the extras if any exist
if (extras != null) {
JSONArray extraNames = extras.names();
for (int i = 0; i < extraNames.length(); i++) {
String key = extraNames.getString(i);
String value = extras.getString(key);
extrasMap.put(key, value);
}
}
sendBroadcast(obj.getString("action"), extrasMap);
callbackContext.success();
return true;
}
PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
callbackContext.sendPluginResult(res);
return false;
} catch (JSONException e) {
callbackContext.error(e.getMessage());
return false;
}
}
#Override
public void onNewIntent(Intent intent) {
if (this.onNewIntentCallback != null) {
this.onNewIntentCallback.success(intent.getDataString());
}
}
void startActivity(String action, Uri uri, String type, Map<String, String> extras) {
Intent i = (uri != null ? new Intent(action, uri) : new Intent(action));
if (type != null && uri != null) {
i.setDataAndType(uri, type); //Fix the crash problem with android 2.3.6
} else {
if (type != null) {
i.setType(type);
}
}
for (String key : extras.keySet()) {
String value = extras.get(key);
// If type is text html, the extra text must sent as HTML
if (key.equals(Intent.EXTRA_TEXT) && type.equals("text/html")) {
i.putExtra(key, Html.fromHtml(value));
} else if (key.equals(Intent.EXTRA_STREAM)) {
// allowes sharing of images as attachments.
// value in this case should be a URI of a file
i.putExtra(key, Uri.parse(value));
} else if (key.equals(Intent.EXTRA_EMAIL)) {
// allows to add the email address of the receiver
i.putExtra(Intent.EXTRA_EMAIL, new String[] { value });
} else {
i.putExtra(key, value);
}
}
((DroidGap)this.cordova.getActivity()).startActivity(i);
}
void sendBroadcast(String action, Map<String, String> extras) {
Intent intent = new Intent();
intent.setAction(action);
for (String key : extras.keySet()) {
String value = extras.get(key);
intent.putExtra(key, value);
}
((DroidGap)this.cordova.getActivity()).sendBroadcast(intent);
}
}
If you are using Phonegap 2.9, so the "Plugin" needs to be "CordovaPlugin".
But if you see, the return type of both are different. "Plugin" expects return as a "PluginResult" instance, where as "CordovaPlugin" expects return as a boolean value, and the callback is triggered using "CallbackContext" instance. some thing like
callbackContext.success("Message : OK");
or
callbackContext.error("Expected one non-empty string argument.");
You can have a deep look into this over the docs here http://docs.phonegap.com/en/2.9.0/guide_plugin-development_android_index.md.html#Developing%20a%20Plugin%20on%20Android