In the beginning of this year, I watched the AngularJS's talk at Devoxx onParleys. After that, I went to ParisJUG to see the technical talk about AngularJS.
And I thought: it seems to be a great JavaScript framework, I must try it!
To try it, I wrote a small application which consume a REST service.
The application is similar to the application I wrote for the post: put it alltogether, and consumes the same REST service.
1 - Call a REST service in AngularJS.And I thought: it seems to be a great JavaScript framework, I must try it!
To try it, I wrote a small application which consume a REST service.
The application is similar to the application I wrote for the post: put it alltogether, and consumes the same REST service.
Normally in AngularJS if you want to call a REST service, you have to write something like this:
angular.module('myModule', ['ngResource'], function($provide) { $provide.factory('musics', ['$resource', function($resource) { return { getArtistBeginBy: function(beginByP) { return $resource('http://localhost\\:8080/RESTfulServices/rs/ArtisteNameBeginningBy/:beginBy').get( { beginBy: beginByP } ); } } }]); }); function SearchCtrl($scope, $resource, musics) { $scope.search = function() { $scope.listMusic = musics.getArtistBeginBy($scope.yourSearch); } }But because, my REST service uses JAXB as JSON serializer, I have an issue when I have "a single element inarray".
My service returns something like this:
{"music":{"albumTitle":"A tout moment","artisteName":"Eiffel","id":"14"}}
Instead of:
{"music":[{"albumTitle":"A tout moment","artisteName":"Eiffel","id":"14"}]}
And ng-repeat of AngularJS don't like that ;)
To work around this issue, I alter the data returned by $resource.
When the data returned by $resource are not empty (not undefined) and are not an array, I'm in case of "a single element in array", then:
- I create an array
- I put the data returned by $resource (single element) in the array
- and I replace the data returned by $resource by the array
js/search.js |
angular.module('myModule', ['ngResource'], function($provide) { $provide.factory('musics', ['$resource', function($resource) { return { getArtistBeginBy: function(beginByP) { return $resource('http://localhost\\:8080/RESTfulServices/rs/ArtisteNameBeginningBy/:beginBy').get( { beginBy: beginByP } , //params function (data) { //success if (! (data['music'] instanceof Array)){ if (typeof data['music'] != 'undefined'){ var myArray = new Array(); myArray.push(data['music']); data['music'] = myArray; } } }, function (data) { //failure //error handling goes here } ); } } }]); }); function SearchCtrl($scope, $resource, musics) { $scope.search = function() { $scope.listMusic = musics.getArtistBeginBy($scope.yourSearch); } }2 - Use the service and bind the result in the html page.
index.html |
<!doctype html> <html ng-app="myModule"> <head> <link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css"> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.js"></script> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular-resource.js"></script> <script src="./js/search.js"></script> </head> <body ng-controller="SearchCtrl"> <div> <br> <input type="text" ng-model="yourSearch" class="search-query" placeholder="Enter an artist name here" ng-change="search()"> <hr> <table border="1" class="table table-striped"> <thead> <tr> <th>ID</th> <th>Artist Name</th> <th>Album Name</th> </tr> </thead> <tbody> <tr ng-repeat="m in listMusic.music"> <td>{{m.id}}</td> <td>{{m.artisteName}}</td> <td>{{m.albumTitle}}</td> </tr> </tbody> </table> </div> </body> </html>3 - Add Cross-origine resource sharing (CORS) to Jersey REST services
And finally, because I want to call my REST service from any domain, I add CORS to Jersey REST Service.
Now, I can have a standalone Angularjs's application (outside the web application).
To do that, I add a filter to the Jersey servlet.
The filter
ResponseCorsFilter.java |
package paddy.jersey.cors; import com.sun.jersey.spi.container.ContainerRequest; import com.sun.jersey.spi.container.ContainerResponse; import com.sun.jersey.spi.container.ContainerResponseFilter; public class ResponseCorsFilter implements ContainerResponseFilter { @Override public ContainerResponse filter(ContainerRequest req, ContainerResponse contResp) { contResp.getHttpHeaders().putSingle("Access-Control-Allow-Origin", "*"); contResp.getHttpHeaders().putSingle("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); String reqHead = req.getHeaderValue("Access-Control-Request-Headers"); contResp.getHttpHeaders().putSingle("Access-Control-Allow-Headers", reqHead); return contResp; } }Filter declaration
web.xml |
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <servlet> <servlet-name>ServletAdaptor</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name> <param-value>paddy.jersey.cors.ResponseCorsFilter</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>ServletAdaptor</servlet-name> <url-pattern>/rs/*</url-pattern> </servlet-mapping> <session-config> <session-timeout> 30 </session-timeout> </session-config> </web-app>
AngularJS standalone source code
NetBeans project of the service with CORS
Aucun commentaire:
Enregistrer un commentaire