Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

OSGi and Spring Data for simple (Web) Application Development - Christian Baranowski


Published on

OSGi Community Event 2014

Published in: Technology
  • Be the first to comment

OSGi and Spring Data for simple (Web) Application Development - Christian Baranowski

  1. 1. OSGi and Spring Data for simple (Web) Application Development Christian Baranowski Content of my talk in a sentence „Java development with Bndtools and bnd is so much fun!“ My Talk in three Words - „Bndtools is cool!“
  2. 2. Bndtools Easy, powerful and productive way to develop OSGi applications. Based on bnd and Eclipse. „Development should be fun, so you need the right tools!“
  3. 3. enRoute • Getting started with OSGi → enRoute project • The talk is based on the ideas from the enRoute blog demo project • enRoute OSGi blog sample project by Peter Kriens • Step by step tutorial from Peter Kriens • Last OSGi Code Camp (Ludwigsburg 2013) was based on this step by step tutorial
  4. 4. Running Blog Example OSGi Framework (Equinox) MySQL … HTTP Server (Jetty) JPA (EclipseLink) Web Browser (IE, FF, Chrome, Safarie..) HTTP / 80 MySQL JDBC / 3306 Web Layer Persistence Layer
  5. 5. Persistence Layer (JPA) .configuration Configuration extender" configuration/*.yaml javax.persistence.EntityManagerFactory" Blog …jdbc.DataSourceFactory …cm.ConfigurationAdmin Eclipse Gemini dbaccess mysql osgi.configuration.yaml …cm.ManagedServiceFactory" Service PID: gemini.jpa.punit Apache Felix" Config Admin Eclipse Gemini JPA JPA extender create service" javax.persistence.EntityManagerFactory Bundle Manifest contains" Meta-Persistence header org.eclipse.persistence.jpa com.mysql.jdbc org.yaml.snakeyaml
  6. 6. Spring Data Extender register the dynamic implementation of the service osgi.jpa.springdata … JPA-Repositories: … provider MANIFEST.MF Extender for JPA Repositories public interface BlogRepository extends JpaRepository<Blog, Long> { ! List<Blog> findByTitleContaining(String part); ! } consumer @Entity public class Blog { @Id @GeneratedValue public Long id; public String title; public String content; } extender looks for bundles with " JPA-Repositories headers
  7. 7. Simple Transaction Management provider Service Registry setup a proxy service with the transaction logic @Reference(target = isTransactionalService) public void setService(Service srv) transactional.service = true requieres.tx.mgnt = true consumer osgi.jpa.tx Whiteboard for services which has a " requires.tx.mgnt service property Proxy " Service if (tx.isTransactionOpen()) { return method.invoke(bundleContext.getService(serviceReference), args); } try { tx.begin(); Object result = method.invoke(bundleContext.getService(serviceReference), args); tx.commit(); return result; } catch (Exception exp) { tx.rollback(); throw exp; } finally { bundleContext.ungetService(txMgrServiceReference); }
  8. 8. Spock based OSGi Integration Tests osgi.jpa.springdata" .data Extender for JPA Repositories osgi.jpa.tx requieres.tx.mgnt = true transactional.service = true class BlogRepositorySpec extends Specification { ! @OSGiService BlogRepository blogRepository def setup() { blogRepository.deleteAll() Blog(title: 'OSGi Web Dev')) Blog(title: 'OSGi V.S Java EE')) } def findBlogPostByTitleContainingOSGi() { when: def list = blogRepository.findByTitleContaining("OSGi") then: list.size() == 2 } }
  9. 9. Web Layer
  10. 10. Jersey MVC (Server Side Web-App) Handlebars View (list.hbs): <html> <head> {{#resource type="css"}} /css/app.css {{/resource}} </head> <body> <table class="table table-striped"> <thead> <th>#id</th><th>Title</th><th>Content</th><th></th> </thead> {{#html-table-content columns="id, title, content" resource="blog"}} {{/html-table-content}} </table> {{#html-pagination}} {{/html-pagination}} </body> </html> ! @GET @Produces( MediaType.TEXT_HTML ) @Template(name="list.hbs") public Page<Blog> list( @QueryParam("page") @DefaultValue("0") Integer page, @QueryParam("size") @DefaultValue("10") Integer size) { return blogRepository.findAll(new PageRequest(page, size)); } com.github.jknack." handlebars Controller Method return the model Controller (BlogController): Handlebars " Helpers osgi-jax-rs-connector
  11. 11. Handlebars Helpers … osgi.web.templates" .handlebars.helpers com.github.jknack.handlebars.Helper" name = … …Helper" name=html-pagination Whiteboard for Helpers …Helper" name=html-table-content <thead> <th>#id</th><th>Title</th><th>Content</th><th></th> </thead> {{#html-table-content columns="id, title, content" resource="blog"}} {{/html-table-content}} osgi.web.templates" .handlebars org.glassfish.jersey.server.mvc.spi." TemplateProcessor<String> Whiteboard for " JAX-RS Provides osgi-jax-rs-connector Extend templates and provide components for the HTML UI
  12. 12. Static Web Bundles <html> <head> {{#resource type="css"}} /css/app.css {{/resource}} </head> OSGi way of web dependency management for CSS or JavaScript frameworks osgi.web.bootstrap MANIFEST.MF MANIFEST.MF Require-Capability: bootstrap.css; filter:="(&(version>=3.1.1)(!(version>=4.0.0)))" Provide-Capability: bootstrap.css; version:Version=3.1.1; type=css @Requieres.Bootstrap @Component @Path("/products") public class BlogController More details see aQute.bnd.annotation.headers.RequireCapability" or" aQute.bnd.annotation.headers.ProvideCapability! bnd annotations.
  13. 13. Modern Web Applications HTTP / 8080 REST Resource (API)" JSON UI business logic" data access logic HTML5" JavaScript (CoffeScript, …)" CSS3 (SASS, LESS, ..) JAVA 8" OSGi
  14. 14. Web Bundle build with Yeoman Grunt Bower yeoman Grunt bower • Scaffolding tool for webapps" • Yeoman helps kickstart new projects" • provide a generator ecosystem • JavaScript Task Runner " • Grunt ecosystem is huge" • minification, compilation, unit testing, linting, … • package manager for the web" • solution to the problem of front-end package management" • ecosystem is huge Thats the tool chain web developers love…
  15. 15. Building Web Applications HTTP / 8080 REST Resource (API)" JSON UI business logic" data access logic HTML5" JavaScript (CoffeScript, …)" CSS3 (SASS, LESS, ..) JAVA 8" OSGi yeomen, grunt, bower bndtools Gradle, tests and builds the OSGi and the Web application Web Developers Java Developers (OSGi)
  16. 16. AngularJS REST Consumer (Client) $blogResource (REST Consumer) ! angular.module('blogApp') .factory('$blogResource', ['$resource', function($resource) { return $resource( '/rest/blog/:postId', { postId: '@postId' }, { }); }]); MainCtrl (the controller is using the REST resource to delete a blog entry) angular.module('blogApp') .controller('MainCtrl', ['$scope','$blogResource', function($scope, $blogResource) { $scope.posts = $blogResource.query(); $scope.deletePost = function(post) { $blogResource.delete({postId:}).$promise.then(function() { $scope.posts = $blogResource.query(); }); }; }]);
  17. 17. REST Resource (JAX-RS) Provider @Component @Path("/rest/blog") public class BlogResource implements Resource { ! BlogRepository blogRepository; ! @Reference(target = isTransactionalService) public void setBlogRepository(BlogRepository blogRepository) { … } @GET public List<Blog> query() { return blogRepository.findAll(); } @GET @Path("/{id}") public Blog get(@PathParam("id") Long id) { return blogRepository.getOne(id); } @POST public void post(Blog blog) {; } @DELETE @Path("/{id}") public void delete(@PathParam("id") Long id) { blogRepository.delete(id); } } A REST Resource build in standard and flexible way based on JAX-RS
  18. 18. Integration Testing REST Resources" transactional.service = true class BlogResourceSpec extends Specification { ! @OSGiServiceRegistration(properties=["transactional.service = true"]) BlogRepository mockBlogRepository = Mock(BlogRepository) def getProductsByExistingId() { given: mockBlogRepository.findOne(42) >> new Blog(title: 'OSGi in Action', content: '-') when: Client client = ClientBuilder.newClient(); Response response = client .target("http://localhost:8080") .path("halres").path("blog").path("42").request().get(); then: response.status == Status.OK.statusCode } HTTP / 80
  19. 19. Testing AngularJS Controllers // Initialize the controller and a mock scope beforeEach(inject(function ($controller, $rootScope, $injector) { scope = $rootScope.$new(); $httpBackend = $injector.get('$httpBackend'); $httpBackend.expect('GET', '/rest/blog').respond([{id: 1}, {id: 42}]); MainCtrl = $controller('MainCtrl', { $scope: scope }); })); it('should send a request to delete a blog post', function () { $httpBackend.expect('DELETE', '/rest/blog/42').respond(200, 'success'); $httpBackend.expect('GET', '/rest/blog').respond([{id: 1}]); scope.deletePost({id: 42}); $httpBackend.flush(); expect(scope.posts.toString()).toBe([{id: 1}].toString()); });
  20. 20. Technologie Stack • Modern Web-Application OSGi Stack • AngularJS (Superheroic JavaScript Framework) • Jetty (Web Server) • osgi-jax-rs-connector (Jersey) • Spring Data JPA (for simple JPA Services) • Spock (testing and specification framework) • Eclipse Equinox or Apache Felix as powerful OSGi Framework
  21. 21. Feedback „Erik Meijer: Are you saying you cannot write large programs in Java? Anders Hejlsberg: No, you can write large programs in Java. You just can’t maintain them. „ Quelle - Compose small “applications” (modules) in to large systems. Quelle -
  22. 22. Resources • OSGi Simple Blog App (Source, Slides)