Java Callout questions

Not applicable

I have following questions on java callout.

1. How to change response status code in javacallout. It always returns 500 error. I need to change 400 for some scenarios. I tried with following but they are not working.

 msgCxt.setVariable("response.status.code", "401");
 msgCxt.setVariable("error.status.code", "401");
 msgCxt.setVariable("response.status", "401");
 msgCxt.setVariable("error.status", "401");
 msgCxt.setVariable("message.status", "401");
 msgCxt.setVariable("message.status.code", "401");

2. Is there Java API document and java object model (similar to javascript object model) documents are available for Apigee Java classes?

3. The sample provided in http://docs.apigee.com/api-services/content/how-handle-java-callout-errors is not working. It returns following error.

{
    "fault": {
        "faultstring": "tried to access method com.apigee.flow.execution.ExecutionResult.<init>(ZLcom/apigee/flow/execution/Action;)V from class com.aig.jwt.apigee.JavaError",
        "detail": {
            "errorcode": "Internal Server Error"
        }
    }
}
3 3 895
3 REPLIES 3

Not applicable

I am looking at the exact same and have not found a suitable solution either. I want to do some authorization in a proxy PreFlow but noticed that neither response code can be set nor any of the FaultRules will kick in ... very confusing.

I'm sorry to hear you're having the same difficulty. You're not alone! I agree that the object model is not as nice as it could be, or should be. I've proposed a workaround in my answer, see below. I hope it will satisfy.

Also, I'm sorry about the delay in responding.

I'm sorry about the delay in responding to your very good questions.

First, the javadoc for the classes you need when implementing a Java callout, are available here: https://github.com/apigee/api-platform-samples/tree/master/docs

If you examine the MessageContext and the ExecutionContext, you'll see there is no specific way to set the status code or the reason phrase. I'm not sure if this is an oversight or if it was intended to be designed this way.

It surely is frustrating to use messageContext.setVariable("response.status.code", 401) and see no effect. By the way, per the documentation, I think that status code variable is defined to be an integer, not a string. But in any case, it's bothersome that it does not work the way you expect.

Unfortunately I don't have a way to avoid that problem, directly. I do have a pattern for you, that will allow you to set a status code and reason phrase within the callout, and then propagate those values to the response message. You can use a Condition on a Step, and then use an AssignMessage within that Step. It looks like this:

    <Flow name='my-flow'>
      <Description>do my thing and return a response</Description>
      <Request/>
      <Response>
        <Step>
          <Name>Java-DoMyThing</Name>
        </Step>
        <Step>
          <!-- 
            The callout sets a variable with a well-known name.
            Check it, and if it is set, propagate the information
            set there to the response message.
           --> 
          <Condition>rc_status_code != null</Condition>
            <Name>AM-DynamicResponse</Name>
        </Step>
        <Step>
          <!-- else, set a static response -->
          <Condition>rc_status_code = null</Condition>
            <Name>AM-DefaultStaticResponse</Name>
        </Step>
      </Response>
      <Condition>(proxy.pathsuffix ~ "/t1") and (request.verb = "GET")</Condition>
    </Flow>


What is happening there?

  1. The flow invokes the Java callout
  2. the java callout does ... something. Then conditionally sets a variable with a well-known name, for example "rc_status_code" in the event of failure. The Java callout always returns ExecutionResult.SUCCESS so as to prevent the flow from entering Fault Processing.
  3. The Conditional step checks that variable, and if it is present, uses an AssignMessage to propagate the information to the response messge.

The AM-DynamicResponse looks like this:

<AssignMessage name='AM-DynamicResponse'>
  <Remove>
    <Headers/>
  </Remove>
  <Set>
    <Payload contentType='application/json'>{
  "message" : "{rc_reason_phrase}",
  "system.uuid" : "{system.uuid}",
  "now" : "{system.time}"
}
</Payload>
    <StatusCode>{rc_status_code}</StatusCode>
    <ReasonPhrase>{rc_reason_phrase}</ReasonPhrase>
  </Set>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>

The StatusCode and ReasonPhrase elements in the AssignMessage both take "Message Templates" as text values. That means the variables referenced within curly braces will be resolved at runtime.

I hope this makes sense and is helpful. It's one extra step beyond a Java callout, in order to set the status code and etc. But maybe it allows you to do what you need.

Please find a working example proxy, along with source code for the Java callout, here.