Sunday, February 12, 2017

Heroes turned into Frankenstein (part II)

Part II. This is the second post in a series documenting my exploration of and attempt at learning angular2.  Here is the first post.

Styles.  Once I had my app logging in and could route to specific modules, I had a set of learning tasks I wanted to accomplish.  The first was to apply a set of styles.  The go-to for styling for the lazy is of course Bootstrap.  Someone has already established an angular2 bootstrap 4 angular npm module called ng2-bootstrap that offers up angular2 components.  I decided to use this set of components to build the tour of heroes crud functionality found in the hero-crud module in my app.  For some reason I forgot to do the "create" portion of the module.  Maybe I'll add that later.  Somewhere along the way I decided to look at angular material design and created a small sample app to play with it.  I thought about converting the app to all material design.  I spun up a quick angular-cli app and created a form on a card with a nav bar at top.  I liked the look but it still feels kind of buggy: fields pre-filled by chrome are not recognized by the controls and the placeholder texts writes over the pre-fill text.  I decided to stick with bootstrap for the learning app.

Components.  When looking for components, I am usually thinking about the more complex set of components that offer a lot of data/ functionality such as data tables or treeviews.   I started looking at datatable wrappers in angular.  The two I ended up playing with are ng2-table from the same people to did the ng2-bootstrap, and angular2-datatable.  At this point my backend was only serving up the few heroes I had started playing with as from the original angular tour of heroes.  This data store only has 2 columns and I only populated about 10 rows from the original example.  Knowing I wanted a better set of sample data I fell back to my old example schema I have used in prior posts that has a Company, Department, Employee set of tables.  I usually populate with only a few rows, but I really want to test pagination on these tables.  To create the data, I wrote a data generation app in groovy to spit out a bunch of inserts of randomly generated employees for my employee table.  I next had to add the REST path through the backend app to the Employee data objects and ended up writing a full set of REST operations for employees.  This became the basis for the remainder of the tables based work I did.  I wired in the calls to employee REST service to my two table examples.  I ended up with a good representation of how these two data table approaches work within the angular bootstrap ecosystem.

PrimeNG and Trees.  I took a bit of a side trip into looking at the PrimeNG set of components newly released for angular 2.  I was able to quickly add the PrimeNG table example.  I'm not sure at this point if I am becoming proficient at adding components, but this seemed to come together rapidly for me.  I was pretty happy with the functionality of the PrimeNG datatable and how easy it was to work with.  I added row selection and coded events that responded to the selection.  I also ended up playing with the treeview component which took me down another rabbit hole of how to pull a tree style structure from my REST back end.  I ended up writing a REST service for Company rather than using the Employee service and added a GET operation ("/treenodes") to return JSON tailored for the PrimeNG Tree component.  I look at the popular JSTree jQuery component as the gold standard for trees and it feels like the PrimeNG component, while functional, has room for improvement when compared to JSTree.  I see some attempts at wrapping JSTree for angular 2 but they kind of looked like they were not ready for prime time.

One more.  I feel like I have one more post to go to cover my exploration into angular2 or angular.   I did some form work, side trip into writing events (2-way binding), and cover a lot of ground in websockets and STOMP.   I'll save this for the last post.

Saturday, February 11, 2017

Heroes turned into Frankenstein (part I)

Starting at Tour of Heroes.  In my last post I had just redone my tour of heroes app for the newly released angular (angular2, 4?, whatever).  I had added a spring boot back end for the heroes service and all went well.  But what I really wanted was do a deep-ish dive with angular-cli and the angular router.  This led down a rabbit hole of exploration into the angular ecosystem.  I have arrived at the other end with some interesting (to me anyway) technology findings and an overall appreciation for where angular currently is from a framework maturity level.  This blog entry will document some of that discovery.  The source for client and server is on my github account.

First stop: Security. For some reason I take a somewhat masochistic interest in web security.  I don't really enjoy working in that space but I never feel like I can start even a play project without solving this problem of authentication and authorization.   As a learning exercise I decided to implement a JWT (json web token) approach with the goal of keeping my backend as stateless as possible.

JWT Server.  As there are two sides to this coin, server and client, I started with the server.  I'm using spring boot and was hoping the spring security project provided a module out of the box for JWT.  No such luck.  I ended up utilizing a series of web posts to learn about implementing the JWT handling with spring security.  Pretty much my entire server side JWT handling ended up being lifted from this repo on github.  It uses spring security and plugs in JWT handling in the right spots.  I have a simple User/Authority/UserAuthority set of tables in Postgresql that I use for authn/authz.  I then used the JWT handling code from the repo to manage token creation, handling and validation within a filter.

JWT Client. I next turned to angular.  I had already implemented routing within the app and added a route/component to log in.  I used the angular2-jwt library to help implement the passing of the JWT token on all REST calls to the server.  The general idea with JWT is that once the user is logged in, all http calls have the token attached (cookie or header) from the client side and the server (in my case a filter on spring boot) will pull the token and validate/authenticate the user.  Angular2-jwt accomplishes this on the client by providing an AuthHttp object which takes place of the normal http object through which you make your rest calls.  AuthHttp just wraps http and adds the token to the call.  I currently store the token in local storage.  This has the weird effect of never logging me out.  Somewhere the expiration time is being ignored, but I'll leave that and the large topic of JWT for another blog post.

Angular-cli, routes, and components.  When I first started working on this play application the router code generation had just been pulled from angular-cli with the promise that it would show back up.  Apparently routing had changed from router version 2 to 3 and it was very different and blah.  What it meant for me was that as I generated components for my application using "ng g c my-component",  I would have to manually wire in the routes.  Not really a big deal. But, as I started looking into the routing generation, I discovered that there was a way to lazy load an entire module of components via a routing subset.   This is kind of interesting.  Knowing that your app is gonna be pulling LOTS of javascript, being able to segment off a module that will be downloaded on demand is pretty awesome.  Not only that, but through a massive googling session, I had run across someone mentioning that the generation of the code to pull this off was still in angular-cli but was not documented.  It turn out that you can invoke "ng g m my-module --routing" and angular will generate the module, component, and set up the routes array.  Just a little wiring from the main route would set up the newly generated module to be lazy loaded.  The simplest example of this in my source is the app routing module and comp2 routing module.  As I am new to TypeScript and not what one would call a proficient Javascript developer, I stumbled for over a week as to the export syntax to achieve this load on demand module approach which culminated in my public a-ha moment on Stack Overflow.  There was immense satisfaction in seeing this load on demand actually work in chrome, seeing the webpacked module only pull down when needed.  Good stuff.

More to come.  Just now realizing I have too much to post in just a single blog entry so I'll leave off here.  In my next post I hope to include my work with different grid/table components,  treeview components, angular forms,  bootstrap and material styling, prime-ng components and a whole lot around websockets and STOMP protocol. Maybe 2 more posts!

Part II here.