Unable to call my restful service from angularjs app using $http - json

I am unable to read JSON from rest webservice using angularjs $http. I have a simple rest webservice in a different project which return JSON. When I try to hit rest service from angular it goes to error part.
Below is my code:
Restful service in Java :
package com.demoapp.rest;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.Consumes;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
/**
* REST Web Service
*/
#Path("Employee")
public class EmployeeResource {
#Context
private UriInfo context;
/**
* Creates a new instance of EmployeeResource
*/
public EmployeeResource() {
}
/**
* Retrieves representation of an instance of com.demoapp.rest.EmployeeResource
* #return an instance of java.lang.String
*/
#GET
#Produces("application/json")
public String getJson() {
//TODO return proper representation object
return "({\"id\":3,\"name\":\"Joe\"})";
}
/**
* PUT method for updating or creating an instance of EmployeeResource
* #param content representation for the resource
* #return an HTTP response with content of the updated or created resource.
*/
#PUT
#Consumes("application/json")
public void putJson(String content) {
}
}
Angularjs code :
angular.module('myApp.controllers', [])
.controller('MyCtrl1', ['$scope', '$http', function($scope, $http) {
$http.jsonp(
/*Doesn't work*/ 'http://localhost:8080/mavenproject1/webresources/Employee?callback=JSON_CALLBACK'
/*Works*/ /*'http://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&callback=JSON_CALLBACK'*/
)
.success(function(data) {
console.log('Success '+data);
})
.error(function(data) {
console.log('Error '+data);
});
}])
.controller('MyCtrl2', [function() {
}]);
I am getting error for first url (localhost..) and same angularjs code works for another public restful service.
Can anyone please tell why angularjs returns error in console for (http://localhost..) restful service and goes to success for (http://api.openweathermap.org/....) ?
Where exactly am I going wrong?

You are trying to access a resource by jsonp but your REST service returns plain json. You need to use
$http.get('http://localhost:8080/mavenproject1/webresources/Employee').
The url http://api.openweathermap.org works because they return the jsonp format. You need this format if you make request to other domains. Jsonp means that the result is wrapped in a function call. The name of the function is dynamically generated and is specified by the callback parameter in your example.
EDIT (results from the discussion above - in production this app will also run on two different servers, so there are the following options to solve the problem)
1) you may use the Access-Control-Allow-Origin header in your jboss server. Have a look at this answer how to do this: Set response headers not using filter - RESTeasy.
2) you may use a reverse proxy in front of your tomcat and your jboss server. For example the apache webserver can do this. Here is an answer that addresses this problem: How to correctly configure a reverse proxy with Apache, to be used for cross-domain AJAX?
3) you can switch to jsonp - this is a little bit complicated because it is not supported directly by RESTEasy. Have a look at this post: How enable JSONP in RESTEasy?

Related

Dynamic parameter as part of request URI with Apache HttpCore

I am looking for existing solutions to match dynamic parameters with HttpCore. What I have in mind is something similar to constraints in ruby on rails, or dynamic parameters with sails (see here for example).
My objective is to define a REST API where I could easily match requests like GET /objects/<object_id>.
To give a little bit of context, I have an application that creates an HttpServer using the following code
server = ServerBootstrap.bootstrap()
.setListenerPort(port)
.setServerInfo("MyAppServer/1.1")
.setSocketConfig(socketConfig)
.registerHandler("*", new HttpHandler(this))
.create();
And the HttpHandler class that matches the requested URI and dispatches it to the corresponding backend method:
public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context) {
String method = request.getRequestLine().getMethod().toUpperCase(Locale.ROOT);
// Parameters are ignored for the example
String path = request.getRequestLine().getUri();
if(method.equals("POST") && path.equals("/object/add") {
if(request instanceof HttpEntityEnclosingRequest) {
addObject(((HttpEntityEnclosingRequest)request).getEntity())
}
[...]
For sure I can replace path.equals("/object/add") by something more sophisticated with RegEx to match these dynamic parameters, but before doing so I'd like to know if I am not reinventing the wheel, or if there is an existing lib/class I didn't see in the docs that could help me.
Using HttpCore is a requirement (it is already integrated in the application I am working on), I know some other libraries provide high-level routing mechanisms that support these dynamic parameters, but I can't really afford switching the entire server code to another library.
I am currently using httpcore 4.4.10, but I can upgrade to a newer version of this might help me.
At present HttpCore does not have a fully featured request routing layer. (The reasons for that are more political than technical).
Consider using a custom HttpRequestHandlerMapper to implement your application specific request routing logic.
final HttpServer server = ServerBootstrap.bootstrap()
.setListenerPort(port)
.setServerInfo("Test/1.1")
.setSocketConfig(socketConfig)
.setSslContext(sslContext)
.setHandlerMapper(new HttpRequestHandlerMapper() {
#Override
public HttpRequestHandler lookup(HttpRequest request) {
try {
URI uri = new URI(request.getRequestLine().getUri());
String path = uri.getPath();
// do request routing based on the request path
return new HttpFileHandler(docRoot);
} catch (URISyntaxException e) {
// Provide a more reasonable error handler here
return null;
}
}
})
.setExceptionLogger(new StdErrorExceptionLogger())
.create();

How to make my Apex class return or "run" a JSON? using APEX REST

I am using the following code to generate a JSON for a Salesforce custom object called Resource Booking. How can I "run" the file (or call responseJSON) so that when I input the custom URL (in the first comment) it jumps to a page similar to this example web page? https://www.googleapis.com/customsearch/v1?json
Here is my code:
#RestResource(urlMapping='/demo/createTask/*') //endpoint definition > {Salesforce Base URL}/services/apexrest/demo/createTask/
global class ResourceBookingTransfer {
public List<Resource_Booking__c> resourceBookingList{get; set;}
public ResourceBookingTransfer(ApexPages.StandardController controller) {
//getResourceBookingList();
}
#HttpGet //HttpGet request
global static responseWrapper getResourceBookingList() {
responseWrapper responseJSON = new responseWrapper(); //responseWrapper object for API response
responseJSON.message = 'Hello World';
return responseJSON; //return the JSON response
//resourceBookingList = Database.query('SELECT Booking_ID__c, Booking_Name__c, Start_Date_Time__c, End_Date_Time__c, Resource__c FROM Resource_Booking__c');
}
//wrapper class for the response to an API request
global class responseWrapper {
global String message {get;set;} //message string
//constructor
global responseWrapper() {
this.message = '';
}
}
}
To just test it - it might be simplest to use https://workbench.developerforce.com. There's "REST explorer" menu in there. Your code should be available under resource similar to /services/apexrest/demo/createTask.
Why that url? Read https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_rest_code_sample_basic.htm
Once you're happy with this manual testing - you can try to do it from outside workbench. Workbench logs you in to SF and passed header with valid session id in the background. If you want to call your service from another website or mobile app - you need to perform login call first, get the session id and then run your code. There are several OAuth flows you can use to do this depending in what your app needs, maybe start with this one: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_username_password_oauth_flow.htm

Minimum spring boot configuration for OAuth2 server and client

I tried to code a 'Hello world' type of exercise to learn Spring Boot support for OAuth2, and the minimum required configuration.
Components:
Authorization server
webapp, which will call the auth server to authenticate the user, and will greet him
Expected flow:
I open the webapp
I get redirected to auth server
I login to auth server
I approve the requested scope
I get redirected back to webapp
I see a greeting (webapp should fetch my username from auth server)
The last point fails with 401:Could not obtain access token.
Last redirect link is http://localhost:9001/ui/login?code=wcXMG4&state=JEEYqC
Am I too naive to assume that the below code&configuration should suffice for my expected flow?
Auth server:
#SpringBootApplication
#EnableAuthorizationServer
#EnableResourceServer
#RestController
public class AuthServer {
public static void main(String[] args) {
SpringApplication.run(AuthServer.class);
}
#GetMapping("/whois")
Principal whois(Principal principal) {
return principal;
}
}
Auth server properties:
server.port=9000
server.contextPath=/sso
security.user.name=joe
security.user.password=password
security.oauth2.client.clientId=SOMEAPP
security.oauth2.client.clientSecret=SECRET
security.oauth2.client.authorized-grant-types=authorization_code,refresh_token,password
security.oauth2.client.scope=read
security.oauth2.resource.userInfoUri=http://localhost:9000/sso/whois
Webapp:
#SpringBootApplication
#EnableOAuth2Sso
#RestController
public class UiServer {
public static void main(String[] args) {
SpringApplication.run(UiServer.class);
}
#GetMapping("/")
String helloWorld(Principal principal) {
return "Yay, auth server provided identity, you are " + principal;
}
}
Webapp properties:
server.port=9001
server.contextPath=/ui
security.oauth2.client.client-id=SOMEAPP
security.oauth2.client.client-secret=SECRET
security.oauth2.client.accessTokenUri=http://localhost:9000/sso/oauth/access_token
security.oauth2.client.userAuthorizationUri=http://localhost:9000/sso/oauth/authorize
security.oauth2.resource.user-info-uri=http://localhost:9000/sso/whois
After spinning up with debug on, it turns out that security.oauth2.client.accessTokenUri is incorrect.
The right endpoint is not .../oauth/access_token, but .../oauth/token.
Probably the tutorial I was looking at used outdated uri.
With that fix, this minimum config does what's expected of it, so I'll close the question.
The real fun begins when you try to customize it, bypassing the defaults; to me it seems that spring oauth still has major bugs, and requires hacky/unexpected approach to work around them in few use cases.

Cannot recieve DATA from RESTFUL API using IONIC 2 generated provider

So, i'm currently studying Ionic 2 to make hybrid applications. I'm following a course on Udemy but the course's content about HTTP requests to WEB API's is obsolete(it's from the ionic 2 Beta). This is a long question but some of you's who are more experienced on the Ionic 2 framework can just skip to step 8 to save some time. Thanks a lot guys!
I'm trying to retrieve data from this URL:
https: //viacep.com.br/ws/01001000/json/.
It has a space after https:// because stackoverflow won't allot me to post more than one link.
But I'm missing something to save this data on a variable I created.
What I did to this point is:
1) I generated the provider which I called ConnectionService using the CLI ionic generator.
ionic g provider ConnectionService
2) Created a method called getCEP() inside the ConnectionService Provider, which makes an HTTP GET Request
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import 'rxjs/add/operator/map';
/*
Generated class for the ConnectionService provider.
See https://angular.io/docs/ts/latest/guide/dependency-injection.html
for more info on providers and Angular 2 DI.
*/
#Injectable()
export class ConnectionService {
constructor(public http: Http) {
console.log('Hello ConnectionService Provider');
}
getCep(): Promise<Response>{
let response: any = this.http.get("https://viacep.com.br/ws/01001000/json/");
console.log("Response: " + response);
let responsePromise: any = response.toPromise();
console.log("ResponsePromise: " + responsePromise);
return responsePromise;
}
}
P.S.: Here you can see i'm loggin in two steps of the request: The first one is the response before I turn it into a Promise, so I can return it to the page. The second one is after i cast it to a Promise using the toPromise() method.
3)In my view I have a button which has the (click) directive calling the method buscarCEP()
<ion-header>
<ion-navbar>
<ion-title>Teste</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<button (click)="buscarCep()">Request CEP</button>
</ion-content>
4.1) My TypeScript file has imported the ConnectionService Provider and named it ConnectionService.
4.2) I declared the ConnectionService inside the #Component directive under the "providers:" label
4.3) I create an instance of Connection Provider that I call conServ on the constructor's declaration. Also I created a variable called CEP, to store the data that I pull from it.
import { Component } from '#angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { ConnectionService } from '../../providers/connection-service';
/*
Generated class for the MenuTest page.
See http://ionicframework.com/docs/v2/components/#navigation for more info on
Ionic pages and navigation.
*/
#Component({
selector: 'page-menu-test',
templateUrl: 'menu-test.html',
providers: [ConnectionService]
})
export class MenuTestPage {
public CEP: any;
constructor(public navCtrl: NavController, public navParams: NavParams, public conServ: ConnectionService) {
}
6)Then I modify the method buscarCEP() so that it gets that conServe instance and calls the getCEP() method which makes an HTTP Request to the URL given above.
buscarCep(): void{
this.conServ.getCep().then(data =>{
console.log("DATA:" + data);
this.CEP = data;
}).catch(err => {
console.log("ERRO: " + err);
});
console.log("CEP: " + this.CEP);
}
PS.: As you can see, i'm logging three steps into the request: The data when the getCEP() method executes, a possible error called 'err' and by the end of it, the variable CEP that I created before and saved the data value to.
7)When I run the application and click on the button, I get the following screen with the console.logs:
Image of ionic page with snips of the Chrome console
8) As you can see, my logs are returning as follows:
8.1) The "Hello ConnectionService Provider" is from the console.log inside the provider's constructor, so the import of the provider is fine and it is being instantiated.
8.2) the "Response: [object Object]" is from the first console.log() inside the getCEP() method in the provider itself.
8.3) the "RespondePromise: [object Object]" is from the second console.log() inside the getCEP() method in the provider itself, after i casted the response to a Promise.
8.4)"CEP: undefined" comes from the console.log inside the buscarCEP() method, which is called after I click on the Request CEP Button
8.5)"DATA:Response with status: 200 OK for URL: https://viacep.com.br/ws/01001000/json/" comes from the console.log() inside the buscarCEP() method.
9) From this i'm taking that the getCEP() method is being able to connect to the URL, hence why the Response and ResponsePromise logs have an Object attached to them. Also the DATA log tells me that i recieved an OK Response from the server. My question is in regard to CEP: Undefined log. I can't seem to store that object in the variable I created.
I know that this is a long one but I wanted to lay all my cards on the board and explain everything as thoroughly as I could because i'm new to this framework.
Any help is appreciated, thank you for your time!
The Response object is stored in this.CEP. The issue is console.log(this.CEP) is called before the response from the HTTP request is returned within then.Promises are asynchronous.You can check the contents by doing console.log(this.CEP) within then.
So if you were to print the data in the html side, use safe navigation operator ?. e.g: {{CEP?.property}}.
A couple of issues with your code:
You should extract the json data from your response object. I suggest you do:
this.CEP = data.json();
If you want to print the contents of the object you can try console.log(JSON.stringify(data,null,2)).

Why does my response not get zipped when using GZIPContentEncodingFilter

I have a REST method where I want to output gziped content. I have added
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>com.sun.jersey.api.container.filter.GZIPContentEncodingFilter</param-value>
</init-param>
To the servlet in web.xml
I can see that the code goes thru the GZIPContentEncodingFilter class by debugging but output does not get the .gzip prefix and content is not compressed, instead it is normal json. I am using Jersey 1.14.
Method looks like:
#GET
#Path("/fundlight")
#Produces(MediaType.APPLICATION_JSON)
public Response getFundLightList() {
StopWatch watch = new StopWatch();
watch.start();
Collection<Object> objectResults = null;
objectResults = getCacheMap("FundLight").values();
List<FundLight> fundLightList = new ArrayList(objectResults);
watch.stop();
GenericEntity<List<FundLight>> entity = new GenericEntity<List<FundLight>>(fundLightList) {
};
ResponseBuilder builder = Response.ok(entity);
return builder.build();
}
I think it depends on the client request header parameters.
If the request contains an Accept-Encoding header containing "gzip" then the response entity (if any) is compressed using gzip and a Content-Encoding header of "gzip" is added to the response.
See:
http://jersey.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/container/filter/GZIPContentEncodingFilter.html
The easiest approach is to register GZIPEncoder and EncodingFilter:
public class MyApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<>();
classes.add(GZipEncoder.class); // this allows gzipped requests and responses
classes.add(EncodingFilter.class); // this enables any registered encoders
return classes;
}
}
Now your server side can process requests with "Content-Encoding:gzip" and respond gzipped when the client request's header had a "Accept-Encoding:gzip".
You could also tell your tomcat / apache / whatever to do response zipping by configuration. Eg. compression="on" in your server.xml's Connectors (Tomcat 7).