In a standalone java code, using Apache HTTPClient
libs, implementing the NTLM Authentication with SharePoint Server and accessing its Web Service and receiving the huge XML content as response. Now this final output is in String format. Created the Java Call Out Policy and uploaded all the jars. I need some help here,
How to pass the java's final output response to Apigee's response.
My requirement is: If I hit the Apigee API Proxy then I need to receive the Java's output(String) as Apigee's response.
1) Can I use No Target Backend EndPoint since inside the java code I access the SharePoint EndPoint URL and receiving 200 Ok and huge XML response as String
2) Which policy is more appropriate to handle this response?
Appreciate your help! Thanks in Advance.
Hi @P.Ganesan, you have access to the messageContext object within your java code so you can set variables & their values:
messageContext.setVariable("some_variable", "variable_value");
Once you do that, "some_variable" is then available inside any subsequent policies by using the {some_variable} notation.
Some comments on your bullet points:
1) You can definitely use the "No Target" endpoint proxy type and access what ever URLs that you need to within your Java code. AS discussed above you can capture the XML response in a variable that you set on the "messageContext" object. You can use an AssignMessage policy following the Java callout policy which can set the response payload with the value from the variable that is set in the java code.
2) Java callout seems like a good approach, given that you have to do NTLM authentication and Java has good libraries to support it. I am sure there are other options as well.
Thanks a lot for your time & response. I'll try it out and let you know the outcome.
Could you please share me what other options are there?
hi @P.Ganesan,
You can use No Target Backend. On the response path you can have your Java Callout Policy returning the response from your java code, you want to.
You can use messageContext to set the response message:
messageContext.getResponseMessage().setContent(yourResponse);
But if your sharepoint endpoint is an HTTP endpoint, why don't you use a regular Target Endpoint and have your Java Callout or a javascript, set the required headers needed for NTLM authentication?
Thanks a lot for your response and solution. I'll try this...
In my understanding, it is not only about Headers, for Microsoft NTLM, any logic should implement the below "Process Flow". So I've used Apache HTTPClient Libs in my Java code.
"Windows integrated authentication"
is what's known as NTLM authentication. When you receive a HTTP 401 from IIS
with aWWW-Authenticate
header
containingNTLM
.
1.The client requests a protected resource from the server:
GET /index.html HTTP/1.1
2.The
server responds with a401
status, indicating that the client must
authenticate.NTLM
is presented as a supported
authentication mechanism via theWWW-Authenticate
header. Typically, the server closes
the connection at this time:
3.HTTP/1.1401Unauthorized
4.WWW-Authenticate: NTLM
Connection: close
Note that Internet Explorer will only select NTLM if it is the first mechanism offered; this is at odds with RFC 2616, which states that the client must select the strongest supported authentication scheme.
5.The
client resubmits the request with anAuthorization
header containing aType 1 messageparameter. The Type 1 message is Base-64
encoded for transmission. From this point forward, the connection is kept open;
closing the connection requires reauthentication of subsequent requests. This
implies that the server and client must support persistent connections, via
either the HTTP 1.0-style "Keep-Alive" header or HTTP 1.1 (in which
persistent connections are employed by default). The relevant request headers
appear as follows:
6.GET /index.html HTTP/1.1
Authorization: NTLM TlRMTVNTUAABAAAABzIAAAYABgArAAAACwALACAAAABXT1JLU1RBVElPTkRPTUFJTg==
7.The
server replies with a401
status containing aType 2 messagein
theWWW-Authenticate
header
(again, Base-64 encoded). This is shown below.
8.HTTP/1.1401Unauthorized
WWW-Authenticate: NTLM TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA=
9.The
client responds to the Type 2 message by resubmitting the request with anAuthorization
header
containing a Base-64 encodedType 3 message:
10.GET /index.html HTTP/1.1
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGoAAAAYABgAggAAAAwADABAAAAACAAIAEwAAAAWABYAVAAAAAAAAACaAAAAAQIAAEQATwBNAEEASQBOAHUAcwBlAHIAVwBPAFIASwBTAFQAQQBUAEkATwBOAMM3zVy9RPyXgqZnr21CfG3mfCDC0+d8ViWpjBwx6BhHRmspst9GgPOZWPuMITqcxg==
11.Finally, the server validates the responses in the client's Type 3 message and allows access to the resource.
HTTP/1.1200 OK
Pls. share me, if u have some other solution. Thanks again.
what version of Sharepoint? Is NTLM the only authentication mechanism you have available? If so, you will need to do the entire NTLM dance for every request. This is because NTLM auth is valid for the life of the connection, but Edge will not maintain the connection between the Java callout and the sharepoint backend.
Sharepoint 2013 accepts OAuth Bearer tokens. Your API Proxy could obtain and then stash the token, to allow it to be used across multiple requests. Microsoft says: "If you plan to build an app for SharePoint that runs in an remote web application and communicates back to SharePoint using server-side code, you will need to use OAuth."
@Dino Hi Dino,
//This is because NTLM auth is valid for the life of the connection, but Edge will not maintain the connection between the Java callout and the sharepoint backend.//
SharePoint version is 2010.
So, If I can not use Java Call Out for my requirement then what is the benefit of Java Call out... What'll be the best approach if it is backend SP 2010?
More background: In my Standalone Java Code in Eclipse, I'm using Service Account, here apigee host name is added and using this credentials for NTLM dance between apigee and SP,by support of Apache HTTPClient libs.Using this code,I can access the SP GET Call WS and receive the valid response.
Actual requirement is, I want to pass this response to Client App. using Java Call Out Policy.
In this scenario, can I use Java Call out? Please guide me. Thanks!
Yes, you can use the Java call out. You will need to do the NTLM authentication for every request. It will work properly.
NTLM carries significant overhead for this type of integration in that you are authenticating connections, not requests - meaning you will incur the auth overhead on every connection. Keep-alives may help reduce the overhead, but in the end it is almost always better to use another scheme if possible.
I would have Apigee proxy talk to a target that handles NTLM auth.
@Dino @Prithpal Bhogill @Sandeep Murusupalli @sriki77
Hi, What could be the reason for following error
{ "fault": { "faultstring": "flow.execution.ExecutionReturnedFailure", "detail": { "errorcode": "flow.execution.ExecutionReturnedFailure" } } }
Other Details:
error_msg APIGEE Execution Failed Properties
action: ABORT
stepDefinition-async: true
internal: false
stepDefinition-type: javacallout
type: SecurityWrappedExecution
enforcement: request
stepDefinition-continueOnError: false
stepDefinition-displayName: NTLM SP Java Call Out stepDefinition-name: NTLM-SP-Java-Call-Out
stepDefinition-enabled: true
result: false
error: flow.execution.ExecutionReturnedFailure
type: ErrorPoint
state: PROXY_REQ_FLOW
error.class: com.apigee.flow.FlowException
Identifier: fault
@P.Ganesan - this seems like a new question. In the future, Please add a new question instead of providing a new question as an "answer" in an existing question.
It sure looks like you have generated an exception in your Java code. Which exception? I don't know exactly, but what I suggest is that you follow standard Java development procedure for isolating the source and nature of the error. Insert try/catch clauses, and in the catch, you will want to capture and format the stacktrace. Within the catch clause, Put the stacktrace into a context variable so that you can view the exception in the Trace window.
I cannot answer fully here, as this is a comment, not an answer. (This is why it is better to ask a new question as a new question, not in an "answer").
...continuing my prior comment, This is a pattern i use for catching exceptions:
import org.apache.commons.lang.exception.ExceptionUtils; .... try { // ... do things here... } catch (Exception e) { e.printStackTrace(); // goes to MP stdout, not visible in trace String varName = "mycallout_error"; msgCtxt.setVariable(varName, "Exception: " + e.toString()); varName = "mycallout_stacktrace"; msgCtxt.setVariable(varName, "Stack: " + ExceptionUtils.getStackTrace(e)); return ExecutionResult.ABORT; }
The ExceptionUtils class is provided by apache's commons-lang library, which is included in the Apigee Edge runtime. You should compile against v2.6, but you do not need to upload the commons-lang jar when you import your API Proxy containing a Java callout with the above code.
Hi @Dino,
Good answer. Posted it as an article, since it can be helpful for others too!
http://community.apigee.com/articles/5314/debugging-java-callouts.html
@Dino @Sandeep Murusupalli Thank You! Your tips really helped me to fix the exceptions.