Is apache commons like HttpClient library equivalent supported in Apex Code on Salesforce's Force.com Platform? - salesforce

I am trying to perform an external Http REST API callout using Apex Class from within my Salesforce Development Organization.
I was wondering if there is support for an equivalent HttpClient library like that of Apache Commons' HttpClient. Is there one?
From the documentation I realize that one way of doing it would be use the System.Http class to perform the request. Refer here for :Salesforce's System Classes and System.Http.
Example:
public class HttpCalloutSample {
// Pass in the endpoint to be used using the string url
public String getContent(String url) {
// Instantiate a new http object
Http h = new Http();
// Instantiate a new HTTP request, specify the method (GET) as well as the endpoint
HttpRequest req = new HttpRequest();
req.setEndpoint(url);
req.setMethod('GET');
// Send the request, and return a response
HttpResponse res = h.send(req);
return res.getBody();
}
}
The reason I am asking this question is because I remember running across a Apex Code Snippet from a tutorial that used such an API. I cant seem to find it now.
P.S: I understand the the Apex Code is a different language and Java libraries like the HttpClient do not run on the Salesforce platform. And there may not be direct language level way to integrate them both, unless there is a Apex Code binding to the library.

The System.HTTP class and friends is the only way to make HTTP requests from ApexCode. As you say apex is not java and you can't run random java libraries in apex.

Related

How to get session id in static method while making callout

I am working on something which includes LWC with tooling API. I wrote this below method which makes a callout. but when I call this method this method from lwc at that time I'm unable to get session Id, but if I call this same method from the developer console then it works fine.
Apex Code:
#AuraEnabled
public static string getList(String fieldName){
HttpRequest req = new HttpRequest();
req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
System.debug('res------>'+UserInfo.getSessionID());
req.setHeader('Content-Type', 'application/json');
req.setEndpoint('callout:Tooling_Query/query/?q=Select+id,Namespaceprefix,developername,TableEnumOrId+FROM+customfield+Where+developername+LIKE\'' +fieldName+ '\'');
req.setMethod('GET');
Http h = new Http();
HttpResponse res = h.send(req);
System.debug('res------>'+res.getBody());
return res.getBody();
}
When I call it from lwc it returns this
[{"message":"This session is not valid for use with the REST API","errorCode":"INVALID_SESSION_ID"}]
so, how can I get session-id from lwc, I already set up a Connected App and Named Credential by the name of Tooling_Query
and add URL to remote sites.
please help me here.
You can't. Your Apex code called in a Lightning Web Components context cannot get an API-enabled Session Id. This is documented in the Lightning Web Components Dev Guide:
By security policy, sessions created by Lightning components aren’t enabled for API access. This restriction prevents even your Apex code from making API calls to Salesforce. Using a named credential for specific API calls allows you to carefully and selectively bypass this security restriction.
The restrictions on API-enabled sessions aren’t accidental. Carefully review any code that uses a named credential to ensure you’re not creating a vulnerability.
The only supported approach is to use a Named Credential authenticated as a specific user.
There is a hack floating around that exploits a Visualforce page to obtain a Session Id from such an Apex context. I do not recommend doing this, especially if you need to access the privileged Tooling API. Use the correct solution and build a Named Credential.

Intercepting cxf web service header with Apache Camel (Java DSL)

I created a web service client to handle cxf soap web services with apache camel.
String serviceUri = "cxf:http://localhost:10000/myservice?serviceClass=" +
MyRequest.class.getCanonicalName();
from(uri).to("mock:xyz");
The web service receives the soap call but throws an exception since the request requires a handling for wss.
org.apache.cxf.binding.soap.SoapFault: MustUnderstand headers: [{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood.
The reason is, that the service requires ws security, which can be seen by lloking at the request.
<SOAP-ENV:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" SOAP-ENV:mustUnderstand="1">
I found out that I need to implement an interceptor to handle header properties.
My questions:
How can I add an interceptor to handle the header attributes with Camel Java-DSL?
Will this be sufficient to get rid of the SOAP Fault?
You can do it through
cxfEndpointConfigurer option #see: Camel-CXF configuration
(I use Spring (it is much easier)), but I guess for DSL URI will look like:
String serviceUri = "cxf:http://localhost:10000/myservice?serviceClass=" +
MyRequest.class.getCanonicalName() +
"&cxfEndpointConfigurer="+ MyConfigurer.class.getCanonicalName();
by implementing org.apache.camel.component.cxf.CxfEndpointConfigurer you have ability to add an Interceptor inside configureServer method
server.getEndpoint().getInInterceptors().add(new MyJAASLoginInterceptor());
if you run your Camel in container with JAAS (like JBOSS) you can use extension from
org.apache.cxf.interceptor.security.JAASLoginInterceptor
with needed callback handler.
Simple example which validates user/password from WSS header against JBOSS users:
public class MyJAASLoginInterceptor extends javax.security.auth.callback.JAASLoginInterceptor {
#Override
protected CallbackHandler getCallbackHandler(String name, String password) {
return new org.apache.cxf.interceptor.security.NamePasswordCallbackHandler(name, password, "setCredential");
}
}

Restlet CorsFilter with ChallengeAuthenticator

I'm building a RESTful API with the Restlet framework and need it to work with cross domain calls (CORS) as well as basic authentication.
At the moment I'm using the CorsFilter which does the job of making my webservice support CORS requests. But, when I try to use this with a simple ChallengeAuthenticator with HTTP Basic Authentication it won't work as I want it to (from a web site).
When I access the webservice directly via Chrome it works as intended, but when I try it in a small web application written in angularjs (jquery/javascript) and try to access the webservice it does not.
Basically what happens is that when a OPTIONS request is sent to my webservice it will not respond with the headers: 'Access-Control-Allow-Origin', 'Access-Control-Allow-Credentials', etc. as it should. Instead it is sending a respond with HTTP status code 401 saying that the authentication failed.. Is this because the authenticator is overriding the CorsFilter somehow?
My createInboundRoot method can be seen below.
#Override
public Restlet createInboundRoot() {
ChallengeAuthenticator authenticator = createAuthenticator();
RoleAuthorizer authorizer = createRoleAuthorizer();
Router router = new Router(getContext());
router.attach("/items", ItemsServerResource.class);
router.attach("/items/", ItemsServerResource.class);
Router baseRouter = new Router(getContext());
authorizer.setNext(ItemServerResource.class);
authenticator.setNext(baseRouter);
baseRouter.attach("/items/{itemID}", authorizer);
baseRouter.attach("", router);
// router.attach("/items/{itemID}", ItemServerResource.class);
CorsFilter corsFilter = new CorsFilter(getContext());
corsFilter.setNext(authenticator);
corsFilter.setAllowedOrigins(new HashSet(Arrays.asList("*")));
corsFilter.setAllowedCredentials(true);
return corsFilter;
}
(The authorizer and authenticator code is taken from the "official" restlet guide for authorization and authentication)
I've tried alot of changes to my code but none which given me any luck. But I noticed that when setting the argument "optional" in ChallengeAuthenticator to true (which "Indicates if the authentication success is optional") the CorsFilter does its job, but obviously the ChallengeAuthenticator does not care about authenticating the client and lets anything use the protected resources..
Has anyone had a similar problem? Or have you solved this (CORS + Authentication in Restlet) in any other way?
Thanks in advance!
I think that it's a bug of the Restlet CORS filter. As a matter of fact, the filter uses the method afterHandle to set the CORS headers. See the source code: https://github.com/restlet/restlet-framework-java/blob/4e8f0414b4f5ea733fcc30dd19944fd1e104bf74/modules/org.restlet/src/org/restlet/engine/application/CorsFilter.java#L119.
This means that the CORS processing is done after executing the whole processing chain (authentication, ...). So if your authentication failed, you will have a status code 401. It's actually the case since CORS preflighted requests don't send authentication hints.
For more details about using CORS with Restlet, you could have a look at this link: https://templth.wordpress.com/2014/11/12/understanding-and-using-cors/. This can provide you a workaround until this bug was fixed in Restlet itself.
I opened an issue in Github for your problem: https://github.com/restlet/restlet-framework-java/issues/1019.
Hope it helps,
Thierry
The CorsService (in 2.3.1 coming tomorrow) contains also a skippingResourceForCorsOptions property, that answers directly the Options request without transmitting the request to the underlying filters and server resources.

Cloud Endpoints in Java on GAE (not javascript)

Although I do think Cloud Endpoints are quite nifty, it would be great if I could use them directly in my GWT application in Java code, rather than writing masses of JSNI. Is this possible? I cannot find a way.
In other words, I would like to NOT use the Javascript Endpoints client, but all the endpoint methods using Java inside GWT.
I think you could use a simple request using Java's built-in HttpURLConnection object. Something like this:
//The URL would be the one you see when you execute the method from APIs Explorer...
String stringURL = "https://YOUR_APP_ID.appspot.com/_ah/api/API_NAME/VERSION/METHOD_PATH?param1=xxx&param2=yyy";
URL url = new URL(stringURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
And then you could parse the response, using Google's Gson library for example (but that would be another question...).
Note: I've never tried this, but I understand it should be working... If you eventually try it, please comment...

How to call a method in WSDL from Salesforce callout

I m a new bie to the salesforce, and I m trying to get the response by calling a wsdl file from the salesforce.
I dont know how to call a method of the WSDL from HTTP callouts
The code is something Like this :-
//HTTP request
HttpRequest req = new HttpRequest();
req.setEndpoint('domain.com/webservices/wwservice.php?wsdl');
req.setMethod('GET');
ANd I m calling the HTTP request and response from the TestMethod.
The result I m getting is System.HttpResponse[Status=null, StatusCode=0] .
Please help me out in this.
First you need to download the WSDL to your local machine, then upload the WSDL to Salesforce.com (Apex-->Generate from WSDL). This will generate the Apex classes needed to actually call web services described in the WSDL.
Anyway, it's all described here: http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_callouts_wsdl2apex.htm

Resources