Passing custom object via context in JAX-RS CXF - 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

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

send a form parameter from Chrome Advanced REST Client

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.

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.

apache camel #Produce method with Object argument instead of String

I am using Camel's POJO producing e.g.
{
public interface MyListener {
String sayHello(String name);
}
public class MyBean {
#Produce(uri = "activemq:foo")
protected MyListener producer;
public void doSomething() {
// lets send a message
String response = producer.sayHello("James");
}
}
}
The interfaces using method sayHello with string object which used as body in the camel. However, If i try to use any other Object here i get exception from camel saying no TypeConvertor found for BeanInvocation for Conversion java.io.InputStream.
I know is the object was allowed it would have been mentioned somewhere. But i want to reason why it has been done like that and if there's a way to work-around this.
I havent really used POJO messaging as yet. Maybe, an experienced user can help you better with this.
But from what I understand, it should be able to support any kind of object not just string.
The error that you're talking of seems to arise out of a mismatch down the route. I'm guessing there is some kind of issue with the consumption.
Can you please post the exact error stacktrace and the consumer method?
Thanks!
Struggling with the same problem right now. The only obvious workaround so far is to use #EndpointInject instead of #Produce - then you get ProducerTemplate and publish any object:
#EndpointInject(uri = "seda:report-send")
ProducerTemplate reportSender;
Now you can do
Object myObject = new Object();
reportSender.sendBody(myObject);
Or even
Object myObject = new Object();
Map<String, Object> headers = new HashMap<String, Object>();
headers.put("Subject", "Mail subject");
headers.put("contentType", "text/plain");
reportSender.sendBodyAndHeaders(myObject, headers);

Why Future<> result from ApiProxy.Delegate.makeAsyncCall() is never used?

I'm playing with GAE hooks and trying to follow Nick's blog post. But apparently it's somewhat outdated because it doesn't have implementation of makeAsyncCall which exists in my GAE SDK 1.6.1.
Here is snippet of my code
public class MultiTenantHook implements Delegate
{
#Override
public Future<byte[]> makeAsyncCall(final Environment env, final String pkgName, final String method, final byte[] request, ApiProxy.ApiConfig config)
{
Callable<byte[]> callable = new Callable<byte[]>()
{
#Override
public byte[] call() throws Exception
{
return makeSyncCall(env, pkgName, method, request);
}
};
FutureTask<byte[]> task = new FutureTask<byte[]>(callable);
return task;
}
}
This method is being called but returned Future<> is never used by GAE. call() method of inner class is never executed.
Do you know how to make it work?

Resources