send a form parameter from Chrome Advanced REST Client - resteasy

I want to send a form parameter from Chrome Advanced REST Client, however, it comes as null. This my resource class
IKeywordResource.java
#Path("")
public interface IKeywordResource {
#POST
#Path("/upload")
#Consumes("multipart/form-data")
public List<Keyword> uploadKeywords(MultipartFormDataInput uploadFile,
#FormParam("list_format") String listFormat) throws IOException;
}
KeywordResource
public class KeywordResource implements IKeywordResource {
#Inject
public KeywordService keywordService;
#Override
public List<Keyword> uploadKeywords(MultipartFormDataInput uploadFile,
#FormParam("list_format") String listFormat) throws IOException {
return keywordService.upload(uploadFile, listFormat);
}
}
And this is how I send the POST request and define the form parameter.
However, as I said list_format comes as null that I dont know why. I will appreciate for any kind of help

You are trying to map the request payload twice. You can either map all parameters to a MultipartFormDataInput object and retrieve your parameter with uploadFile.getFormDataMap().get("list_format"); or you map each parameter with #FormParam.

Related

How to pass Salesforce Flow variables into Apex Class with correct scope?

I'm trying to use a use a Flow in Salesforce to pass variables into an Apex Class that performs an HTTP Post to an external API. The Flow grabs an Opportunity, parses some of its fields, and inputs them into the Apex class. From there, the Apex class calls an InvocableMethod to create a custom object to store these inputs as a list of strings and then pass them to a 'webservice' class that creates a JSON object of the data and POST it to the API.
I'm able to get the POST to work properly with hard-coded strings but when I try to use the input variables the Flow errors out saying that The input parameter "xxxxxx" isn't available in the referenced action. Remove it from the "Apex-Class-xxxx" Action element.
In the debug screen of the Flow I can also see that these inputs are grabbing the correct values from Salesforce but it errors out saying: An invalid input parameter was specified for Apex action
How do I get these inputs to properly go into the Apex class?
global class MyApexClass
{
//Stores output from 'sendToWebService' to be converted to JSON
public class Body {
public String address;
public String companywebsite;
public String companyname;
public string opportunityid;
}
//Stores inputs from Flow
public class FlowInputs {
#InvocableVariable public String Address;
#InvocableVariable public String CompanyWebsite;
#InvocableVariable public String CompanyName;
#InvocableVariable public String OppId;
}
//Method to call webservice method since InvocableVariables can't be passed to it directly
#InvocableMethod(label='xxxx' description='xxxxx')
public static List<String> sendToWebService(List<String> flowData){
List<String> outList;
for (String input : flowData){
outList.add(input);
}
SendToAPI(outList);
return outList;
}
//creates an object to store inputs, converts to JSON, and sends it to the API via HTTP POST
webservice static void SendToAPI(List<String> accountData){
Http m_http = new Http();
HttpRequest req = new HttpRequest();
.........
You're basically there -
On the invocable method, you need to declare a list/array of the apex object you made to store the inputs, not a list of strings:
#InvocableMethod(label='xxxx' description='xxxxx')
public static List<String> sendToWebService(List<FlowInputs> request)
Then, you should be able to do the formatting of the json within the request header/body method itself

How to pass parameters to a Camel route?

It is possible to pass parameters to a Camel route?, for instance, in the next code snippet:
public class MyRoute extends RouteBuilder {
public void configure() throws Exception {
from("direct:start")
.to("cxf:bean:inventoryEndpoint?dataFormat=PAYLOAD");
}
}
The value for dataFormat is in hard code, but, what if I want set it dynamically?, passing a value from the code where route is called. I know this is possible adding a constructor and passing parameters in it, like this:
public class MyRoute extends RouteBuilder {
private String type;
public MyRoute(String type){
this.type = type;
}
public void configure() throws Exception {
from("direct:start")
.to("cxf:bean:inventoryEndpoint?dataFormat=" + type);
}
}
There is another way?
Thanks so much!
As you mentioned, you can use a constructor (or setters or any other Java/Framework instruments) if the parameters are static from a Camel point of view.
The parameters are configurable in the application, but after the application is started they do no more change. So, every message processed by the Camel route uses the same value.
In contrast, when the parameters are dynamic - i.e. they can change for every processed message, you can use the dynamic endpoint toD() of Camel. These endpoint addresses can contain expressions that are computed on runtime. For example the route
from("direct:start")
.toD("${header.foo}");
sends messages to a dynamic endpoint and takes the value from the message header named foo.
Or to use your example
.toD("cxf:bean:inventoryEndpoint?dataFormat=${header.dataFormat}");
This way you can set the dataformat for every message individually through a header.
You can find more about dynamic endpoints on this Camel documentation page

Is it possible to return a text/plain from Google Cloud Endpoints?

I want to return just a simple blob of text from Google Cloud Endpoints that would be interpreted by the client as nothing but a text file. Is this possible?
I know it is not possible to return primitives, but can I return an HttpServletResponse and set the content myself or something?
Disclaimer: Not tested, just a braindump.
Cloud Endpoints uses ProtoRPC as the underlying transport, which encodes messages as JSON over the wire. You can't change this behavior. The simplest way to return a text file is to just define a simple message class with one String member for the text file:
public class TextFile {
private String text;
// getText, setText methods ...
}
Then your Endpoints method would look something like this:
#Api(name = "my_api", ...)
public class MyAPI {
#ApiMethod(name = "myapi.returntext", httpMethod = "get)
public TextFile returnText() {
TextFile response = new TextFile;
response.setText(read_text_from_some_source());
return response;
}
}
You'll get a trivial JSON response from this method which should be easy enough to parse the text data out of:
{ "text": "<contents_of_text_dump>" }
The response may have some extra fields such as 'kind' and 'etag' which you can ignore.
Of course the simplest method if you just want to dump out some text is to forget about Endpoints altogether and just set up a GET handler:
public class ReturnText extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
response.getWriter().write(read_text_from_some_source());
}
}
You can then map this to whatever endpoint url you wish in your web.xml.

Passing custom object via context in JAX-RS CXF

I have an InInterceptor that gets some information from the HTTPHeaders and creates a custom object
public void handleMessage(Message message) throws Fault {
final HttpServletRequest request = (HttpServletRequest) message
.get(AbstractHTTPDestination.HTTP_REQUEST);
String a= request.getHeader("A");
String b= request.getHeader("B");
message.put("CustomObject", new CustomObject(a,b));
}
Then in service methods I use below code to get the custom object
final Message message = PhaseInterceptorChain.getCurrentMessage();
final CustomObject customObject=(CustomObject)message.getContextualProperty("CustomObject");
I was wondering if its possible to get this through #Context ..
#GET
#Path("/custom")
#Produces("application/json")
public List<Node> getA(#Context("CustomObject") String user) throws XYZException;
Thanks

How can I add HTTP Request Header to Silverlight RIA Requests

I have a need to pass an HTTP header for each an every RIA Service request being made from a Silverlight app. The value of the header needs to come from the app instance, and not from a cookie. I know this can be accomplished by putting it in the DTOs, but it's not an option because a lot of our service calls use Entities and change sets, so there's no base class to tie into for all requests. So I'm looking for a centralized and safe means to pass something back with each request so the developers do not have to worry with it. A custom HTTP header would work fine, but I don't know how to intercept the outbound request to set it.
Anyone have any ideas I can try?
On the lower level you can add HTTP headers with the help of an IClientMessageInspector. Try starting from this post on SL forum.
The next step depends on your use cases.
If the value of the header must be the same for any method called by the DomainContext, then you may just extend the context using partial class, add a property for the header value and use that property in the inspector.
If you need to pass a different value for each method call, you'd probably need to wrap your DomainContext into another class and add an argument to each method of the context that will accept the header value and pass it to the inspector somehow. Needless to say, without a code-generator this would be hard.
Here's an adapted sample from the SL forum for the first case:
public sealed partial class MyDomainContext
{
public string HeaderValue { get; set; }
partial void OnCreated()
{
WebDomainClient<IMyDomainServiceContract> webDomainClient = (WebDomainClient<IMyDomainServiceContract>)DomainClient;
CustomHeaderEndpointBehavior customHeaderEndpointBehavior = new CustomHeaderEndpointBehavior(this);
webDomainClient.ChannelFactory.Endpoint.Behaviors.Add(customHeaderEndpointBehavior);
}
}
public class CustomHeaderEndpointBehavior : IEndpointBehavior
{
MyDomainContext _Ctx;
public CustomHeaderEndpointBehavior(MyDomainContext ctx)
{
this._Ctx = ctx;
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(this._Ctx));
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) { }
public void Validate(ServiceEndpoint endpoint) { }
}
public class CustomHeaderMessageInspector : IClientMessageInspector
{
MyDomainContext _Ctx;
public CustomHeaderMessageInspector(MyDomainContext ctx)
{
this._Ctx = ctx;
}
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) {}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
{
string myHeaderName = "X-Foo-Bar";
string myheaderValue = this._Ctx.HeaderValue;
HttpRequestMessageProperty property = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
property.Headers[myHeaderName] = myheaderValue;
return null;
}
}

Resources