Archive for the 'Web' Category

March 11th, 2020
12:43 pm
Using self signed SSL with Spring Boot

Posted under Java & Spring & Spring Boot & Web

I needed to use ssl for a Spring Boot backend web service for Yoti, as https is a Yoti requirement.

This post here details how to do this for Spring Boot. The official Oracle docs can also be found here.

The following configuration fragment from the Spring Boot application.properties shows how to configure for ssl using the created keystore (keystore.p12), which was placed in the deployment directory alongside the spring boot jar:-

server.port=8443
server.ssl.key-store-type=PKCS12
server.ssl.key-store=salientsoft.p12
server.ssl.key-store-password=<password>
server.ssl.key-alias=salientsoftdev

Comments Off on Using self signed SSL with Spring Boot

March 11th, 2020
12:34 pm
Using the node http-server over self signed ssl

Posted under Angular & Web

Instructions for setting up http-server for https use may be found here.

To do this I used the same certificate/key combination (but renamed as required) that I created for setting up ssl over WAMP, in my previous post here. As with the WAMP post/installation, the certificate/key were created using openssl, which I downloaded here. The official openssl site may also be found here.

From my previous WAMP installation, I took the certificate.crt/private.key combination from the apache conf folder, and renamed them to cert.pem/key.pem respectively, and placed them in a new ‘keys’ folder conveniently accessible by the batch files that ran all the microapps. I then created ssl versions of all the batch files to run the microapps – an example of the fabric batch file follows:-

cd dist\microapp-fabric-prototype
http-server -p 443 -S -C ..\..\..\keys\ss-localhost-cert.crt -K ..\..\..\keys\ss-localhost-cert.key

https then worked fine and I was able to integrate with the live Yoti for age verification.

Comments Off on Using the node http-server over self signed ssl

March 4th, 2020
6:28 pm
URL Parameter changes when switching to HttpClient

Posted under Angular & Web

From Angular 4.3 onwards, the HttpClient is preferred over the old Http service.

When creating and passing URL parameters, the new HttpParams object must be used.

Details and examples of this are shown here.

Note carefully as per the post that when passing parameters to the http methods e.g. get, the json property name is now ‘params’ instead of ‘search’, and the append method should be called to add parameters (although the last poster indicates that calling set worked for him as well).

Another gotcha is that the HttpParams object is also immutable, so that every time you add a parameter a new object is created/returned and you must use the returned object, e.g. in fluent style when adding multiple parameters, otherwise you will end up using your empty initial HttpParams object.

Comments Off on URL Parameter changes when switching to HttpClient

March 3rd, 2020
2:13 pm
combineLatest changes when upgrading to rxjs 6

Posted under Angular & RxJS & Web

Note that you must now call this as a function rather than a method of another observable, see here.

Also note that as before you can use a projection function to map the results, as an alternative to using .pipe(map…)). If you are using the projection function, you should not use the spread syntax with the projection as the last argument as this is deprecated. Rather pass the observables as an array, followed by the projection function. More details on the project are here, and in the code examples here.

 

Comments Off on combineLatest changes when upgrading to rxjs 6

March 3rd, 2020
11:43 am
Angular build fails with “Progress Plugin Invalid Options”

Posted under Angular & Web & Webpack

When upgrading an angular 4 project (places-admin) to angular 6, I got the above error when building.

The problem and solution are detailed here.

The issue appears to be caused by webpack 4.25.* breaking compatibility with the plugin.

Applying the fix in the above post solved the problem, by adding

“webpack”: “4.24.0”

to the devDependencies section in package.json

 

Comments Off on Angular build fails with “Progress Plugin Invalid Options”

February 20th, 2020
4:34 pm
Loading/Busy Indicator

Posted under Angular & PrimeNG & Web
Tags

I needed an indicator such as some kind of spinner whilst microapps were loading.

PrimeNG has a progress spinner here. However, the implementation uses scalable vector graphics, which I was not able to use.

My base line for browser support included IE11, and unfortunately this only has a partial implementation which broke when using the PrimeNG spinner.

I therefore used loading.io to design my own animated gif. The site has a number of free as well as paid for spinner/busy patterns, and each one has a form allowing a number of variables to be tweaked, allowing customisation of your spinner design. You can then download the result in a choice of formats including animated GIF as well as SVG. I stuck with an animated GIF as this worked across all the browsers. I designed different versions (e.g. colour), making them themeable as part of the application theme. For each base theme I implemented a choice of 2 spinners – A rolling spinner, and a spinning circles spinner. Both gave excellent results and were free.

 

Comments Off on Loading/Busy Indicator

February 20th, 2020
4:19 pm
Deep merging of JS objects

Posted under Angular & Web

I needed to do this to implement a configuration profile/configuration override pattern, whereby a configuration profile contained json configuration which would selectively override some configuration options by merging the profile into the overall configuration.

This post here discusses deep merging of objects, and gives examples such as this one, which I used as the basis of my implementation. I did not need or want to get into deep merging of arrays, which other answers discussed, and I did not want to involve lodash.

 

Comments Off on Deep merging of JS objects

February 20th, 2020
3:15 pm
Using the Angular APP_INITIALIZER

Posted under Angular & Web

This allows the use of asynchronous operations (such as configuration loading) at Angular bootstrap time. It is documented (somewhat minimally to say the least) here.

In my case I needed it to allow early script loading of (in my case Yoti) external scripts at bootstrap time. A Yoti script overwrote some promise code that had already been patched by zone.js earlier. Subsequently, zone.js detected this and the application failed. This is documented here. I also used it to load the app configuration dynamically, rather than from index.html. As well as being a better design due to decoupling from index.html and opening the door to pulling the configuration from an external provider, this also allowed multiple configuration sets to be selectable e.g. from a query string parameter in the url.

This Stack Overflow post shows how to implement the APP_INITIALIZER.  This tutorial post does the same, and goes into details about using multiple providers via a multi provider token. Basically you need to pass a function or a lambda which returns a promise, which completes when your asynchronous operation is done. One point worthy of note is that when rejecting a promise, you need to pass something in the reject, or Angular throws an error stating Cannot read property ‘ngOriginalError’ of undefined.

My implementation is here:

@NgModule({
declarations: [
AppComponent,
FabricComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,

],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [
…,
ConfigurationService,
ConfigurationValidator,
ScriptLoader,
PreBootScriptLoader,
ObjectUtils,
{
provide: APP_INITIALIZER,
useFactory: (configurationService: ConfigurationService, preBootScriptLoader: PreBootScriptLoader) => () => {
  return configurationService.load().then(() => preBootScriptLoader.load);
},
deps: [ConfigurationService, ConfigurationValidator, PreBootScriptLoader, ScriptLoader, ObjectUtils],
multi: true
},
],
bootstrap: [AppComponent]
})

Promise rejection code fragment showing passing an error in the reject:

if (this.configurationValidator.validate(appConfig)) {
  console.error(‘Configuration failed validation’, appConfig);
  reject(new Error(‘Configuration failed validation as above.’));
} else {
  resolve();
}

Comments Off on Using the Angular APP_INITIALIZER

February 6th, 2020
10:27 pm
Zone.js gives errors if Promise code is patched via external js after zone is loaded

Posted under Angular & Web

When integrating a microapp which uses the Yoti identity platform for age verification, I hit issues where other microapps would fail to load after the Yoti/age verification microapp had loaded.

The following error appeared on the browser console:-

Error: Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.
Most likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)
at Function.push../node_modules/zone.js/dist/zone.js.Zone.assertZonePatched (polyfills.js:6911)
at new NgZone (vendor.js:42512)
at getNgZone (vendor.js:43220)
at PlatformRef.push../node_modules/@angular/core/fesm5/core.js.PlatformRef.bootstrapModuleFactory (vendor.js:43116)
at vendor.js:43162
at www.yoti.com/:1

A similar instance of this issue, where Bing loads after zone.js and similarly patches promise code, is detailed here.

In my case the culprit was the Yoti client SDK, which did the patching/overwriting. A temporary fix, which worked successfully, was to load the Yoti SDK in index.html, prior to the angular bootstrap process, and remove/disable my existing code which loaded the SDK dynamically via a script tag (after zone had loaded).

My final solution was to use an Angular app initializer token, which permits a custom initialise function to be created. This can perform  an asynchronous operation to be performed which returns a promise to the app initialiser, which allows bootstrapping to continue only when the promise has succeeded.

The details of this implementation are in a separate post, here.

Comments Off on Zone.js gives errors if Promise code is patched via external js after zone is loaded

February 6th, 2020
7:43 pm
Remote loading of Angular Elements from separate webpack bundle causes unwanted multiple bootstraps

Posted under Angular & Web

I have used this pattern here from Manfred Steyer (a Google Developer Expert who has been involved in coding the Angular 8 Ivy release), to allow remote loading of separately developed and packaged Angular Elements, each of which is build like a separate app.

Whilst the application was able to successfully load and display a number of angular elements as separate microapps, the bootstrapping process had issues, manifested with console errors stating ‘zone.js already loaded’.

This post here discusses this kind of issue. Whilst I did not experience the same failure as detailed in the post, it was a related issue.

It has also been raised as an angular issue here.

Rob Wormald’s comment of 14/5/18, after he looked into it, indicated that renaming the global webpackJsonp objects to something unique in each bundle would solve the problem, but was not a recommended solution. From the discussion in the post comments, it looks like Angular 8 and 9 have a better solution to this issue.

I am not yet able to upgrade Angular from the 6.1.7 I am currently using to 8 or 9. PrimeNG has compatibility with the latest Angular version, and also switching to a much later PrimeNG would cause me theming issues as Prime have dropped the legacy theming for a newer, paid for, non open source theme creator, which raises further issues.

As my current work is a POC, I therefore took a pragmatic approach and implemented Rob Wormald’s idea as above. One of the posters in the thread above took this approach using a custom webpack solution as detailed here. I took a similar approach but avoided the custom webpack solution by using a simple NPM post build script, written in javascript, run with Node, which runs after the webpack bundle has been created. The script uses the replace plugin to rename the objects in the files. One reason was that I wanted to be decoupled from any direct webpack customisation via a webpack build plugin as from the comments there can be issues getting this to work depending on the actual Angular version in use. I have seen comments that the angular development team are keen to encapsulate/hide the internals of webpack building to allow them the complete ability to control and change it. In fact this has happened with later angular versions.

Whilst any such solution will be temporary and will need to be swapped out when eventually moving to Angular 9 or later, this solution completely solved the problem, and zone.js was no longer loaded multiple times.

The solution involved the following steps:-

1) Add a postbuild step in package.json, to run the post build script:-

“scripts”: {
“ng”: “ng”,
“start”: “ng serve”,
“prebuild”: “cd src/assets/resources/themes/salient && node-sass theme.scss theme.css –source-map .”,
“build”: “ng build”,
“postbuild”: “node post-build.js”,

The postbuild step is automatically run when you use “npm run build” to do a build. This step edits the built bundle to do the required renaming.

Note also that in the above example I also have a prebuild step, which is used to build SCSS themes which are deployed as static assets outside the bundle, to allow dynamic theme selection. The prebuild step also runs automatically when “npm run build” is done.

2) The post build script uses the npm replace package. Note that using the replace from javascript rather than a CLI command avoids the collision with the standard Windows replace, and also allows a tidier way of handling the various components of the Webpack script bundle.  An example of the code follows. Note that as node uses the V8 javascript engine, array maps and lambdas “=>” are available to use:-

var replace = require(“replace”);

/* arguments: Object suffix, project folder name (dist subfolder),
*            list of all the generated webpack scripts to be updated */
doWebpackReplace(‘MicroappFabric’,’microapp-fabric-prototype’,
[‘main.js’, ‘polyfills.js’, ‘runtime.js’, ‘styles.js’, ‘vendor.js’]);

function doWebpackReplace(name, filename, paths) {
   replace({
      regex: ‘\\[“webpackJsonp”\\]’,
      replacement: `[“webpackJsonp${name}”]`,
      paths: paths.map((p) => `dist\\${filename}\\${p}`),
      recursive: false,
      silent: false,
   });
}

3) Make sure the npm file replace package is installed via “npm install –g replace”, and make sure it is listed in the “dependencies” section of package.json:-

“primeng”: “6.1.3”,
“replace”: “^1.1.5”,
“rxjs”: “6.3.2”,

Comments Off on Remote loading of Angular Elements from separate webpack bundle causes unwanted multiple bootstraps