Michelle BranchIt is difficult to categorize the music of Michelle Branch. She is at times a rock singer, a country singer, a folk singer, and a pop singer. 

Wednesday night at Park West, she was all these things.

For nearly two hours, Ms. Branch played before a packed house of devoted fans, who cheered and sang along to her songs.

Branch's fame peaked in the first half of the 2000's decade when she released back-to-back-to-back hit albums and a string of hit singles. She raked in a string of awards during this period, including a Grammy for "The Game of Love" - a collaboration with Carlos Santana.

While her airplay may have waned in the past fifteen years, her enthusiasm has not. She played all the hits from those years and made them sound fresh. And she mixed in some recent music (she released a new album - "The Trouble with Fever" - earlier this year. Everything was delivered with the energy one would expect from someone who enjoys performing.

Park West has great acoustics for music but spoken words do not transmit well there; so, I did not know what she was saying between songs; but those who heard seemed to greatly appreciate it.

It was an evening in which the crowd drew energy from the performer and the performer drew energy from the crowd.

It was a great evening!


Roxy MusicRoxy Music never received the recognition they deserved. In the 1970s and 1980s, they were leaders in the progressive rock music movement. Bryan Ferry's smooth crooner's voice was backed by outstanding musicians like Phil Manzanera (lead guitar), Andy MacKay (saxophones), and Paul Thompson (drums). Roxy's singles never made much noise on the US charts, but they received plenty of airplay on the album-oriented-rock stations of the time and their concerts were always a big draw.

The group disbanded in 1983, following the release of their excellent final album "Avalon". They reformed and toured in the early 2000s then broke up again. It has been over a decade since they toured and almost 40 years since they performed in Chicago.

They returned to the Windy City Monday night at the United Center. 

It should have been a big draw. It was the band's 50th anniversary, their first tour in years, and the core of the original group (Ferry, Manzanera, MacKay, and Thompson) participated. But the concert failed to sell out, so the venue closed off the upper deck, moved the stage forward two sections, and reshuffled tickets to make the arena seem fuller. 

The illusion of fullness did not work, but that did not matter to those in attendance. Roxy Music put on a polished performance, playing for nearly two hours. They selected works from their early artsy days ("In Every Dream Home a Heartache") to their later pop-influenced songs ("More Than This", "Dance Away").

They chose to omit some of their more popular songs (Roxy had a dozen Top 10 hits in the UK), filling the set with many deep cuts from their eight studio albums instead. They still sounded great. Ferry's velvety voice is still strong, the core members still have great technical prowess, and the musicians they hired to fill out the arrangements were top-notch.

This was a concert I had to attend. I grew up listening to Roxy Music. I had never seen them live before, and there is a good chance this is their final tour before they separate for good. 

I made the right choice coming to the show.


In a previous article, I showed how to refactor a controller and move the business logic into its own service class. We based that service class on an interface.

NOTE: The code for the previous article can be found here. If you did not work through the samples in that article, you can use this code as a starting point for this article.

When we called that service, we explicitly instantiated an instance of the class we created. That works, but it hard-codes a dependency to a specific implementation, which limits our flexibility.

In this article, I will show you how to use Dependency Injection to remove that hard-coded dependency. Spring explicitly supports Dependency Injection.

Declaring a class as a Service

The MathServiceImpl class contains our business logic. To use Spring's Dependency Injection, we must explicitly declare it as a Service. To do this, we decorate the class with the @Service attribute. If we have multiple implementations of the same interface, we distinguish them by also decorating the class with the @Qualifier attribute and providing a unique string to identify this implementation. I typically use the class name as this string, but you may use whatever conventions you like to enforce uniqueness.

An example is shown in the listing below:

public class MathServiceImpl implements MathService {
    public Integer AddNumbers(Integer firstNumber, Integer secondNumber) {
        Integer sum = firstNumber + secondNumber;
        return sum;

    public Integer SubtractNumbers(Integer firstNumber, Integer secondNumber) {
        Integer difference = firstNumber - secondNumber;
        return difference;

We can create a second Service class that implements this same interface and provide a different Qualifier, as shown below:

public class MathServiceMockImpl implements MathService {
    public Integer AddNumbers(Integer firstNumber, Integer secondNumber) {
        return 10;

    public Integer SubtractNumbers(Integer firstNumber, Integer secondNumber) {
        return 5;

In this example, we heard coded the return values of the add and subtract methods to 10 and 5, respectively.

This is a common practice if we want to use one class for production and a different class for testing. The production class may contain dependencies to other services, databases, and files; while the testing class may hard code return values to avoid hitting those dependencies.

Instantiating the service class

Now that we have declared the MathService classes as services, we no longer need to explicitly instantiate them: we can now use Dependency Injection to automatically instantiate a class whenever it is used.

In the MathController class, delete the two lines that instantiate MathServiceImpl:

MathService mathService = new MathServiceImpl();

Instead, at the top of the class, add a private variable named "mathService" of type MathService and decorate this with the @Autowired attribute and the @Qualifier attribute. Pass "MathServiceImpl" as the argument to @Qualifier, as shown below:

private MathService mathService;

The @Autowired attribute tells Spring to use Dependency injection to create an instance of an object whenever the mathService variable is used.

The @Qualifier attribute tells Spring which class to instantiate.

Here is the new full listing of the MathController class:

public class MathController {

    private MathService mathService;

    public ResponseEntity Add(
        @PathVariable("firstNumber") Integer firstNumber, 
        @PathVariable("secondNumber") Integer secondNumber) {
            Integer sum = mathService.AddNumbers(firstNumber, secondNumber);
            return new ResponseEntity(sum, HttpStatus.OK);

    public ResponseEntity subtract(
        @PathVariable("firstNumber") Integer firstNumber, 
        @PathVariable("secondNumber") Integer secondNumber) {
            Integer difference = mathService.SubtractNumbers(firstNumber, secondNumber);
            return new ResponseEntity(difference, HttpStatus.OK);

When we run this and call the add method, we get the same results as in the last article, but we have fewer hard-coded dependencies.

Fig. 1

Using a Different Qualifier

We can tell Spring to use a different implementation of MathService by changing the @Qualifier argument.

Replace the @Qualifier line in MathController with the "MathServiceMockImpl", as shown below:

private MathService mathService;

Now, when we run this and call the add method, it always returns 10, regardless which parameters we pass, as shown in Fig. 2.

AddNumbers Mock Implementation
Fig. 2


In this article, I showed you how to use the built-in Dependency Injection features of Spring Boot to avoid hard-coded dependencies in your code.

You can find the sample code here.


In a previous article, I showed how to create a REST API in a Spring Boot application. In the demo we built, all the logic was in the Controller. For a complex application, this can violate the Single Responsibility principal, as the controller method is responsible for both returning data in an appropriate format and performing any business logic to retrieve and/or calculate that data, along with performing required workflows. To achieve a better separation of concerns, we should move any business logic out of the controller and into its own service layer. This will not only simplify our code, but it will allow us to deploy and scale the controller and the business logic separately.

NOTE: The code for the previous article can be found here. If you did not work through the samples in that article, you can use this code as a starting point for this article.

Some Business Logic

For this demonstration, I will create a new controller named "MathController" that contains two methods: add and subtract. These methods each accept two parameters and do exactly what their names suggest: find the sum and the difference between those numbers. The code is shown below:

public class MathController {
    public ResponseEntity Add(
        @PathVariable("firstNumber") Integer firstNumber, 
        @PathVariable("secondNumber") Integer secondNumber) {
            Integer sum = firstNumber + secondNumber;
            return new ResponseEntity(sum, HttpStatus.OK);

    public ResponseEntity subtract(
        @PathVariable("firstNumber") Integer firstNumber, 
        @PathVariable("secondNumber") Integer secondNumber) {
            Integer difference = firstNumber - secondNumber;
            return new ResponseEntity(difference, HttpStatus.OK);

If we run this locally and call it from a browser, the output is shown in Fig. 1.

Fig. 1

There is nothing wrong with this code and it is probably acceptable for simple methods like these. But imagine if we were doing much more than performing simple arithmetic. Imagine complex workflows with dependencies on databases, file systems, or web services. Logic like that does not belong in the controller. It should be split into its own service.

We will pretend the logic above is complex and justifies splitting it into a distinct service.


In many cases, it is a good idea to create an interface on which to base your service classes. This supports polymorphism in your app and allows you to use different implementations for different purposes (for production vs for testing, for example).

I will save all my services and interface in a source folder named "services".

An interface defines the public properties and methods of any class that implements it.

We use the interface keyword to define an interface and list the name, input arguments, and return data type of each public method, as shown below:

public interface MathService {
    Integer AddNumbers(Integer firstNumber, Integer secondNumber);
    Integer SubtractNumbers(Integer firstNumber, Integer secondNumber);


Now, we can create a class based on this interface. The implements keyword tells Java on which interface a class is based. If we base a class on an interface, we must implement every method in that interface. The code below shows this.

public class MathServiceImpl implements MathService {

    public Integer AddNumbers(Integer firstNumber, Integer secondNumber) {
        Integer sum = firstNumber + secondNumber;
        return sum;

    public Integer SubtractNumbers(Integer firstNumber, Integer secondNumber) {
        Integer difference = firstNumber - secondNumber;
        return difference;

The @Override attribute tells Java that this the methods override an interface.

Changing the Controller

Now, we can modify our controller to call this service, as shown below:

public class MathController {
    public ResponseEntity Add(
        @PathVariable("firstNumber") Integer firstNumber, 
        @PathVariable("secondNumber") Integer secondNumber) {
            MathService = new MathServiceImpl();
            Integer sum = mathService.AddNumbers(firstNumber, secondNumber);
            return new ResponseEntity(sum, HttpStatus.OK);

    public ResponseEntity subtract(
        @PathVariable("firstNumber") Integer firstNumber, 
        @PathVariable("secondNumber") Integer secondNumber) {
            MathService = new MathServiceImpl();
            Integer difference = mathService.SubtractNumbers(firstNumber, secondNumber);
            return new ResponseEntity(difference, HttpStatus.OK);

If we run this locally and call it from a browser, the output is shown in Fig. 2.

Fig. 2

The results are the same as before our refactoring. The difference is that splitting into a service and interface provides more flexibility and maintainability. That may not be obvious for this simple contrived example; but it is very true for a complex workflow with external dependencies.

Dependency Injection


In this article, I will show you how to separate logic into its own service.

In the next article, I will show you how to simplify this using Dependency Injection.

You can find the sample code here.

Joe Guadagno on Leadership

Comments [0]

Episode 720

Joe Guadagno on Leadership

Joe Guadagno describes the difference between Leadership and Management, what it takes to be a good leader, and how to cultivate leadership among your team.

I first discovered Neil Gaiman's "The Sandman" comic decades ago and I have read it twice. In recent years, the series has gained more attention with the release of a Netflix TV series and an Audible radio play, both of which are excellent.

After consuming The Sandman saga in multiple media, I stumbled upon "Sandman: Book of Dreams" - a 1996 collection of short stories set in the universes occupied by The Sandman. A different writer delivers each story, and the collection is edited by Neil Gaiman and Ed Kramer. Gaiman introduces each story with a brief blurb about the author and his relationship thereto.

"The Sandman" is the story of Morpheus, the god-like creator of and lord of the realm of dreams into which each of us slips every night. But it is also the story of the other worlds in which Morpheus interacts and the characters he meets along the way. This collection visits many of those worlds and many of those characters.

I had read some of the authors (Gene Wolfe, Susanna Clarke) and I knew the names of others I had not read (Clive Barker), but I was unfamiliar with most of the writers in this collection.

The book contains a variety of stories, ranging from folk tales to mysteries to horror stories and monster stories; but one thing I can say for them all; they are all dark. Sometimes very dark.

I have not decided if the following are the best stories in "Book of Dreams", but they were the most memorable to me.


A disturbing tale of the Cereal Convention told from the point of view of a new character.

"Seven Nights in Slumberland"

An interesting crossover between Morpheus and Little Nemo. Little Nemo was the star of "Little Nemo in Slumberland" - a pioneering comic strip from the early twentieth century, which chronicled a young boy's vivid dreams. In this story, those dreams take place in Morpheus's kingdom.

"Escape Artist"

The "Origin Story" of Wanda - one of the more colorful characters in the Sandman saga.

"An Extra Smidgeon of Eternity"

A man is frustrated by the timing of his death because it means he will not hear the end of a story he was enjoying. (Death, as Sandman fans know, is the older sister of Morpheus)

"The Mender of Broken Dreams"

One of Morpheus's subjects wonders about his origins and his own existence. And receives an answer.

"Ain't You 'Most Done"

In the first dream of his life, a rich man gets to do what he always dreamed of doing before he dies.

"Stopp't Clock Yard"

Two London magicians anger Morpheus and he takes his revenge.

I do not know if those unfamiliar with the world of The Sandman will enjoy this collection. I suspect they will. Each story is well-written and coherent, if a bit fantastical. But their connection with the universe and characters Gaiman created make them more special to those of us who count ourselves as fans.


The saga moves forward in "Lord of Chaos", the sixth volume in Robert Jordan's "Wheel of Time" series.

The entire world grows hotter, thanks to the growing power of The Dark One;

Rand, the Dragon Reborn, raises and trains an army in preparation for The Final Battle with The Dark One. But, Rand struggles to control the voice of a long-dead mad king inside his mind.

The rift between factions of the mystical Aes Sedai sisterhood grows wider and more intense.

The female protagonists - in training to become Aes Sedai - get a promotion, including a huge one for Egwayne;

Jordan continues his world building and character evolution that made the previous novels successful; but it suffers from the same weakness as many of its predecessors: the story drags on much longer than it should.

As in the previous stories, a strong ending saves this one.

GCast 131:

Managing Secrets in an Azure Key Vault

Learn how to store and manage secrets in an Azure Key Vault using the Azure Portal.


In a previous article, I showed how to create a simple REST API in a Spring Boot application. I only covered the GET HTTP verb in that article. In this article, I will show how to implement other HTTP verbs and pass models to and from a REST service.

HTTP Supports the following verbs with a request: GET, POST, PUT, PATCH, and DELETE. These verbs map well to common data operations (GET to read data; POST to add data; PUT and PATCH to update data; and DELETE to delete data), but this mapping is not required and developers do not always adhere to it. One advantage a POST request has over a GET request is that you can send large and more complex data in the body of a POST request. A POST request often includes data in the JSON format in its body.

NOTE: The code for the previous article can be found at https://github.com/DavidGiard/Demo-Spring-App/releases/tag/Spring-Boot-REST-API


A model is a class designed to hold data. When we create an instance of a model class, we can use that instance to represent a real or conceptual object and all the properties of that object.

In Java, a model class is created no differently than any other class. I like to create a folder named "models" in which to store model classes. Here, I will create two classes: GreetingInput and GreetingOutput, as shown below


package com.dgtest.models;
public class GreetingInput {
    public GreetingInput(String personName) {
        this.personName = personName;
    public GreetingInput() {

    private String personName;
    public String getPersonName() {
        return personName;
    public void setPersonName(String personName) {
        this.personName = personName;


package com.dgtest.models;
public class GreetingOutput {
    public GreetingOutput(String greeting) {
        this.greeting = greeting;
    public GreetingOutput() {

    private String greeting;
    public String getGreeting() {
        return greeting;
    public void setGreeting(String greeting) {
        this.greeting = greeting;

GreetingInput has one property (personName), along with a setter and a getter for that property.

GreetingOutput has on (greeting), along with a setter and a getter for that property.

In addition, each class contains an overloaded constructor, along with one to set the property's value when an instance is created.

More Controller Methods / More Verbs

As you have probably guessed, we will pass an instance of the GreetingInput class as an input to our method, which will return an instance of the GreetingOutput class. Because we are dealing with HTTP, this data will be passed in JSON format and Java/Spring will automatically convert it into a POJO ("Plain Old Java Object").


My previous article handled HTTP GET requests; but Spring Boot can handle other HTTP verbs, such as POST, PUT, PATCH, and DELETE.

Add the following method to your controller to handle a POST request:

@PostMapping(path="hello", consumes="application/json", produces="application/json")
public ResponseEntity greetPersonPost(@RequestBody GreetingInput greetingInput) {
	String personName = greetingInput.getPersonName();
	String greeting = "Hello, " + personName;
	GreetingOutput greetingOutput = new GreetingOutput(greeting);
	return new ResponseEntity(greetingOutput, HttpStatus.OK);

There are four things to call out in this method:

NOTE: If you do not yet have a Controller method, see this article.

  1. The @PostMapping attribute
  2. The ResponseEntity return type
  3. The GreetingInput input parameter
  4. The @RequestBody attribute

@PostMapping attribute

Notice the @PostMapping attribute on the method. This tells Spring that it will run in response to an HTTP POST request. This attribute contains the following arguments:

  • path="hello": This identifies the relative path in the URL to which the POST request is submitted
  • consumes="application/json": This tells Spring to expect data in the body of the request to be formatted as JSON.
  • produces="application/json": This tells Spring to return response data in JSON format

The ResponseEntity return type

The method returns a ResponseEntity containing an object of type GreetingOutput. We created this class earlier. It has one property: greeting. Although the code generates an instance of a POJO, Spring will automatically convert the object to JSON when sending a response to the client, thanks to the produces argument in the @PostMapping attribute.

The GreetingInput input parameter

This method accepts an object of type GreetingInput - a class we created above that contains one property: personName. The client will supply this in JSON format and Spring will automatically convert it to a POJO, thanks to the consumes argument in the @PostMapping attribute.

The @RequestBody attribute

The greetingInput parameter is decorated with the @RequestBody attribute. This tells Spring to look for the value of the parameter in the Body of the HTTP request.

Calling the Method

The code in this method performs a similar function to the greetPerson method created in the previous article. The main difference is that we return an object, rather than a string.

To test the method, we run or debug it locally; then submit an HTTP POST request to http://localhost:8080/greetings/hello. The body of this request will contain a JSON object with the same properties as the greetingInput class, similar to the following:

    "personName" : "David"

You may choose your favourite tool to submit a POST request. I prefer PostMan, which is a free cross-platform tool that you can download from https://www.postman.com/downloads/

Fig. 1 shows the PostMan interface with the important values highlighted.

Fig. 1

Run or Debug the application locally, then complete the following in PostMan:

At the HTTP verb dropdown, select "POST".

At the Request URL field, enter "http://localhost:8080/greetings/hello"

At the Request Body field, select the "raw" radio button and the JSON data format and enter the following text:

    "personName" : "David"

Click the [Send] button

You should see a response code of "Status: 200 OK" and the following value in the response body:

    "greeting": "Hello, David"

If you receive an error, verify that the app is running and that your URL is correct. Pay attention to the route and the port number. You may also get a clue in the error response message.

Other HTTP Verbs

The process is nearly identical in handling HTTP PUT, PATCH, and DELETE requests. Spring provides the @PutMapping, @PatchMapping, and @DeleteMapping attributes, which work in a very similar way to the @PostMapping attribute.


In this article, I showed you how to implement a method to handle HTTP POST requests from a Java Spring application. You can see the completed code at https://github.com/DavidGiard/Demo-Spring-App/releases/tag/Handle-HTTP-POST-Requests


In a previous article, I showed how to use start.spring.io to create a new Spring Boot application. In this article, I will show how to extend that application and create a REST API.

REST (short for "Representational State Transfer") is an architectural pattern that allows you to access, create, and manipulate backend resources over HTTP.

Spring Boot uses the Model-View-Controller (MVC) pattern for web apps, which separates the business logic, the data model, and the user interface into different components. A web service does not have a user interface, but it returns data to the client - typically as JSON - and we can think of this as the interface.

In the demo described here, we will begin with the sample application created using start.spring.io in the previous article.


In an MVC application, a Controller contains or calls the business logic. By convention, we add controllers to a folder named "controllers".

Create a file named "GreetingsController.java" with a GreetingsController class in the controllers folder. Add a method named "greet" that accepts no parameters and returns a String, as in the following code:

public class GreetingsController {
    public String greet() {
        return "Hello";

Your project should look similar to Fig. 1.

Controller Class
Fig. 1

Identify this class as a controller by decorating the class with the @RestController attribute.

We want to map the greet method to a route, so that users can access it via HTTP. A route specifies the relative URL that maps to a specific method in a controller. An example will help to demonstrate this.

To make Spring recognize this as an MVC controller, decorate the class with the @RequestMapping attribute. Add the parameter "/greetings" to the RestController attribute to indicate the route path of the controller.

We can then make the greet method accessible via HTTP by decorating this method with the @GetMapping attribute with the parameter "greet". GetMapping makes this method available via the HTTP GET verb.

Here is the code, as described so far:

package com.dgtest.dgtest.controllers;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

public class GreetingsController {
    public String greet() {
        return "Hello";

When you run or debug this application locally, it displays output similar to that in Fig. 2.

Run Output
Fig. 2

Notice that it is running locally on port 8080 (I have highlighted the relevant output). Therefore, the host will be http://localhost:8080.

To access methods in the controller class, we append the RequestMapping parameter (in this case "greetings") to the URL. To call a specific method via HTTP GET, we append the GetMethod parameter (in this case "greet" for the greet() method.

So, when the application runs locally, we can call the greet method by sending an HTTP GET request to http://localhost:8080/greetings/greet

Try this by opening a browser and navigating to http://localhost:8080/greetings/greet. This sends an HTTP GET request to that URL.

The string "Hello" should appear in the browser, as shown in Fig. 3.

Http Get
Fig. 3

NOTE: If I deploy this to another web server, the host part of the URL will change. For example, I could create a site named "https://davidsawesomewebaapi.azurewebsites.net" and the URL mapped to this method would be https://davidsawesomewebaapi.azurewebsites.net/greetings/greet

Returning a ResponseEntity

In the example above, we returned a string. This is useful, but HTTP has the ability to return metadata with that string. For example, we may want to know where the request came from or any error information. Information like this can be included in the Header of an HTTP response. Spring provides a ResponsEntity object that returns a full HTTP response to the client, allowing you to customize it, as needed.

The code is shown below:

public ResponseEntity greet() {
 return new ResponseEntity("Hello", HttpStatus.OK);

A ResponsEntity contains an object within it, which will be the body that is returned in the HTTP response. In this case, the body will be the string ("Hello") that we returned to the client in the example above. The difference is that we are returning a full HTTP response. The HttpStatus.OK represents the value 200, which is a standard HTTP response code, indicating that everything worked correctly. Later, when I cover error handling, we can return a different HTTP response code and more information about the error. We can also manipulate the headers of the response before returning it, but that is beyond the scope of this article.

Passing parameters to a REST request

There are a number of ways to pass parameters to a GET request. Spring's MVC capabilities provide a simple way to add extra information to a URL. For example, we may want to create a method similar to greet that accepts a person's name as an argument and call it using a local URL similar to the following:


Currently, the greet method does not accept parameters, so we will create in our controller a new method named "greetPerson" that accepts the personName parameter, as in the following listing:

public ResponseEntity greetPerson(String personName) {
 String greeting = "Hello, " + personName;
 return new ResponseEntity(greeting, HttpStatus.OK);

We must tell the method where to find the value of this parameter. In this case, it is part of the URL, so we modify GetMapping argument and we decorate the personName parameter with the @PathVariable attribute, as shown below:

public ResponseEntity greetPerson(@PathVariable("personName")String personName) {
 String greeting = "Hello, " + personName;
 return new ResponseEntity(greeting, HttpStatus.OK);

The curly braces around personName in the GetMapping path indicate that this is a variable value provided at runtime. The is stored in a temporary variable named "personName" and the PathVariable argument indicates that we should pull the personName value from the URL and assign it to the personName parameter.

Now, when we navigate to http://localhost:8080/greetings/greet/David in a browser, it returns the results shown in Fig. 4.

Fig. 4


In this article, you learned how to create a simple REST API in a Spring Boot application. I only covered the GET HTTP verb. In the next article, I will show how to implement other HTTP verbs and pass models to and from a REST service.

You can find the source code for this article at https://github.com/DavidGiard/Demo-Spring-App/releases/tag/start.spring.io

Episode 719

Don Miller on Headless Content Management Systems

Don Miller describes how he and his team are using Headless Content Management Systems (CMSs) to generate fast, secure web sites from existing CMS systems data.


The Beginner’s Guide to Headless CMSes


Listening to Al Dimeola's albums does not prepare you for seeing Al Dimeola perform live. Nothing prepares you for seeing him perform.

You cannot appreciate his technical excellence until you see his fingers work their magic on his guitar. He brings to his craft the perfect combination of speed and emotion.

Friday night at the City Winery, Mr. Dimeola delighted the crowd with his musical prowess. He is known for a number of different styles, including a significant stint playing jazz fusion - both solo and with the legendary supergroup Return To Forever. But, on this night, he brought only his acoustic guitar. 

For me, his best work was playing Latin music and he served up plenty Friday evening with songs from and inspired by the music of Spain, North America, and South America. He mixed in some classical sounding music. Nearly everything he played was his own composition, but he did treat the audience to an arrangement of Lennon and McCartney's "Norwegian Wood" and at least one Astor Piazzolla tango.

Al was joined by two excellent percussionists, who complemented his music without overpowering it.

I was fortunate to have front row seats and I sat in awe as fingers flew across strings for nearly two hours. He makes a six string guitar sound like a 12-string guitar - sometimes like two 12-string guitars.

He closed with his classic "Mediterranean Sundance" before thanking the audience and exiting without an encore. I could have stayed and heard more, but I did not leave unsatisfied.

I would love to see him again now that I am prepared.



Rocky Mountain Rhapsody

Comments [0]

It has been years since I have been to Colorado, and I have never ventured outside of Denver until this past Labor Day weekend. Two vacation days extended the holiday into a 5-day holiday.

We arrived Thursday evening, greeted some old and new friends, and talked for a bit before resting in preparation for a busy Friday.

First on the agenda (after breakfast, of course) was a guided walking tour of downtown Denver. It was a hot day and my friends only lasted about half of the 3-hour tour; but I was happy to complete it and meet up with them later. We did not go into any buildings but received a good overview of the history and architecture of the city, walking from the state capitol to Civic Center Park to the theatre district to the art museum. It was a nice introduction to the city. In the afternoon, we visited the home of Molly Brown, the "unsinkable" woman who showed bravery and generosity when she survived the sinking of the Titanic. Brown was the estranged wife of a successful miner and spent most of her life in Denver. In the late afternoon, my friend Jerry drove down from his home in the mountains to spend an hour catching up. We have worked together at two different jobs, but rarely see one another face-to-face, so this was a treat.

Saturday morning, we headed west, stopping first at Red Rocks - an amphitheater carved out of the mountain stones from which it derives its name. We arrived too late Thursday to see Robert Plante and Allison Krauss and my friends were not fans enough to stay for the Nine Inch Nails concert in the evening; so, we contented ourselves with walking around the area and a walk through the small museum, which featured photos of the many stars who have performed in this famous venue. If I return to Denver, I hope to see a concert here.

We left Red Rocks and took I-70 toward Vail, stopping first for lunch at Idaho Spring - a small mining town that retains much of its history. A local historical group put on an entertaining skit about a 19th-century robbery next to the railroad tracks and a vintage engine. Our next stop was Georgetown because someone heard that John Denver thought it was the most beautiful town in Colorado. It was nice, but we just drove through, admiring the homes. 

Finally, we arrived in Vail in the late afternoon. This area is spectacular. While Denver is mostly flat, Vail is nestled within the Rocky Mountains which soar on every side. The town is a facsimile of an Alpine village with small shops and cafes along pedestrian roads. We walked these roads and hiked some of the trails along the rivers and mountains and sat at outdoor cafes enjoying the food and watching the world go by. On the final morning, we took the gondola cable car up to the top of a local mountain. From there, the views were spectacular, and I enjoyed watching mountain bikers risk injury as they sped down the mountain at top speeds.

Traffic back to Denver was heavy, as one would expect on a holiday weekend. The one thing I had hoped to do was attend the Colorado Rockies game at Coors Field - one of the few MLB stadiums I had yet to visit. We arrived at our hotel 2 hours after the game started, but I managed to go to the game and watch the final three innings. Check that one off!

Our flight home Tuesday was not until the evening. We began the day at a breakfast place recommended by my son, who attended a Denver wedding earlier this summer. After breakfast, we visited the Denver Art Museum, which has a wide variety of paintings, sculptures, and other forms of art; but is most memorable for its collection of US Southwestern art and Native American art. 

Colorado has astonishing natural beauty - much more than my current home state of Illinois. However, the cultural attractions of Denver are not as compelling as those in Chicago. In addition, Denver suffers from an inordinate number of homeless people. This did not bother me (I encounter the homeless often in Chicago) until our final day when a man began harassing us and went so far as to throw things at the back of my head as I was walking away. Fortunately, no harm came of it. Vail was beautiful but the cost of everything from hotels to meals to lift tickets will keep me from returning too frequently.

It was a good time to go to Colorado. Temperatures were high in Denver, but pleasant in the mountains and we saw no hint of rain or overcast skies. Traveling with friends made it more special and exploring new places is always a pleasure.


Episode 718

Michael Richardson on Yarn Berry

Michael Richardson describes how to use the Yarn Berry package manager to add functionality to your JavaScript applications.

August 2022 Gratitudes

Comments [0]


Today I am grateful to see the Fabulous Thunderbirds in concert last night.



Today I am grateful that I can connect with friends remotely.



Today I am grateful to hear live music at a new park in the West Loop yesterday.



Today I am grateful for a free concert every Thursday evening at Willie Dixon's Blues Heaven Foundation



Today I am grateful for a walk along the Chicago Riverfront last night



Today I am grateful to attend an exciting White Sox - Tigers game last night with family and friends.



Today I am grateful for a visit from my sisters this weekend.



Today I am grateful I can stream movies on demand



Today I am grateful for my annual physical exam.



Today I am grateful to present at the Chicago .NET User Group last night at their first in-person event in over 2 years.



Today I am grateful for wood-fired pizza



Today I am grateful to see "Cruel Intentions: The Musical" on my first visit to the Chopin Theater last night.



Today I am grateful I was able to help an 85-year-old lady resolve her computer issues yesterday.



Today I am grateful for a conversation with Kira yesterday.



Today I am grateful to schedule the travel for 2 vacations this fall



Today I am grateful for dinner with Richard last night in Chinatown



Today I am grateful for my first visit to the Chicago Magic Lounge



Today I am grateful to sleep in for the first time in weeks



Today I am grateful to see The Wallflowers in concert last night.



Today I am grateful to Tim, who picked me up, drove me to my car, and jump-started my dead battery yesterday.



Today I am grateful for a new pair of shoes - a gift from my son.



Today I am grateful for a virtual happy hour yesterday with Tze Lin, Hattan, and Ernesto.



Today I am grateful to update dozens of old passwords and store them in a password manager this week.



Today I am grateful to arrive safely in Colorado last night



Today I am grateful for:

-a guided walking tour of Denver

-a visit to (the unsinkable) Molly Brown home

-hanging out with Jerry in the afternoon



Today I am grateful for:

- a walk around the Red Rocks Amphitheatre

- a visit to Idaho Springs

- my first taste of Colorado-style pizza


The Wallflowers Jakob Dylan will never be the prolific songwriter that his father was. His father, of course, is legendary singer-songwriter Bob Dylan, who revolutionized popular music in the 1960s and won a Nobel Prize in the 2010s. But Jakob shares much of his father's songwriting talent and Bob's habit of building complex lyrics atop simple melodies. And, unlike his father, Jakob can carry a tune.

The younger Dylan is currently 52 years old and has been leading his band The Wallflowers for decades. Saturday evening, he brought The Wallflowers to the SPACE nightclub in Evanston for the first of two shows. The club was packed to see a band that typically plays much larger venues and the Wallflowers did not disappoint.

Dylan's music ranges from folk to rock to hymns to anthems to ballads and he played them all to the delight of the audience. He chatted with the crowd and made eye contact, something his father stopped doing years ago.

I have been to SPACE many times over the years. This was the first time they removed the tables and chairs and hosted a standing-room-only show. This was less than ideal, but it was likely the only way to entice this band to play in such a small room. Arriving early and standing by the stage provided a unique opportunity to relate to Jakob's emotions during the performance. He had the habit of picking out someone in the audience and singing directly to them during each number.

The audience loved hits like "One Headlight" and "6th Avenue Heartache", as well as a rendition of Tom Petty's "The Waiting", but the band performed every song with enthusiasm and received with pleasure.

If I had one complaint about the show it was the lack of lighting on the stage. Some musicians remained in shadow the entire set and no spotlight shone on anyone - even on Dylan.

Local artist Nathan Graham was an excellent choice as a warmup act, performing his original soulful melodies while accompanying himself on guitar.

I originally bought tickets to see The Wallflowers at SPACE in 2011; but an illness in the band forced them to cancel that show. Fortunately, they rescheduled over a year later and I was able to see them for the first time.

It was worth the wait.

GCast 130:

Creating an Azure Key Vault

Azure Key Vault allows you to securely store certificates, encryptions keys, and other secrets. In this video, you will learn how to create an Azure Key Vault.


Spring is a framework designed to build Java applications quickly. Applications built with Spring are flexible because the framework supports many other frameworks, such as Hibernate, Struts, and EJB.


The folks who created Spring provided a page to quickly bootstrap an application. To create your first Spring app, open a browser and navigate to https://start.spring.io/, as shown in Fig. 1.

Fig. 1

At the "Project" field, select the Build Automation tool you want your app to use. Maven and Gradle are both popular tools, so your choice may come down to which tool you and your team are most familiar with.

At the "Language" field, select your language of choice. Java, Kotlin, and Groovy all compile to Java bytecode and run on the Java Virtual Machine (JVM), so they are all compatible with Spring.

At the "Spring Boot" field, select the version of Spring you wish to use. Generally, you should select the latest version that is not a "SNAPSHOT" version. SNAPSHOT versions are created for development and testing and may not be as stable.

At the "Group" field, enter a group ID for the project. This is similar to a project's default namespace in .NET.

At the "Artifact" field, enter a descriptive name for the project.

The "Name" field defaults to your Artifact ID. It is usually fine to accept this default.

At the "Description" field, enter a brief description of your project.

The "Package name" field defaults to the Group ID, followed by ".", followed by the Artifact ID. It is usually fine to accept this default.

At the "Packaging" field, specify whether you want Spring to generate JAR files or WAR files when packaging the application. A WAR file is only appropriate for a web application, while a JAR file can be used for any application. This article explains the differences between the two. I typically select JAR files.

At the "Java" field, select the version of Java your application will use. For a new project, you will likely want to choose the latest Long Term Release (LTS) version of Java. As of this writing, that is version 17. Exceptions would be

  • You need a feature available in a more recent version
  • You are creating an application that must be compatible with a project built using an older version

Click the [ADD DEPENDENCIES] button to add more dependencies to your application. A dialog displays a list of available dependencies, as shown in Fig. 2.

Fig. 2

For example, you can select "Spring Web" if you intend to build a REST API. You can always add dependencies after the project is created, but this wizard makes it easier to do so.

Click the [GENERATE] button to generate the project. The wizard will generate all the necessary folders and files, compress them into a ZIP file, and download that file.

Extract the ZIP file into a location on your hard drive. The structure will look similar to that shown in Fig. 3.

Fig. 3

Open the project in your favourite Integrated Development Environment (IDE). This is a good starting point for your application.


In this article, I showed you how to create a new Spring application using start.spring.io.

You can find the final code here.

Application Insights is a scalable Azure data store and service that is ideal for storing monitoring information of all kinds.

To install an Application Insights service, navigate to the Azure Portal then, click the [Create a resource] button (Fig. 1), and search for Application Insights (Fig. 2) to display the "Application Insights" start page, as shown in Fig. 3.

Create Resource Button
Fig. 1

Search for Application Insights
Fig. 2

Applicatino Insights Description Page
Fig. 3

Click the [Create] button to open the "Application Insights" creation dialog, as shown in Fig. 4.

Create Application Insights Blade
Fig. 4

At the "Subscription" dropdown, select the Azure subscription in which to create the Application Insights service. Most of you will have only one subscription.

At the "Resource Group" dialog, select a resource group in which to store the Application Insights service or click "Create new" to create a new one.

At the "Name" field, enter a unique name for your Application Insights service.

At the "Region" field, select a region into which to deploy this service. Consider the locations of the services that will write to this data store in order to reduce latency.

At the "Resource Mode" field, select "Workspace-based".

At the WORKSPACE DETAILS fields, select the defaults.

Click the [Review + create] button to display the "Review + create" tab, as shown in Fig. 5.

Create Application Insights Blade
Fig. 5

This tab will display any validation errors. Correct them and click the [Create] button to create the Application Insights service.

After Azure creates the service, navigate to its "Overview" blade, as shown in Fig. 6.

Application Insights Overview Blade Fig. 6

The "Overview" blade contains the "Instrumentation Key" (Fig. 7). This is an important piece of information that is often used to connect your application to Application Insights.

Instrumentation Key
Fig. 7

In this article, you learned how to create an Azure Application Insights service.

Episode 717

Michael Scherotter on Galleryst

Using tools from Adobe and Microsoft, as well as open source libraries, Michael Scherotter has created a portal to display photography and artwork within a virtual gallery. He describes how he created galeryst.com and how to use it.

Malcolm sighed. "Do you have any idea," he said, "how unlikely it is that you, or any of us, "will get off this island alive?"

Michael Chrichton was already a bestselling author when he published "Jurassic Park" in 1990. But none of his novels and few novels by other authors had the cultural impact of this one. Steven Spielberg adapted this book into an excellent movie in 1993, which spawned five sequels of varying quality but undeniable popularity.

JP is the story of a billionaire who hires a group of scientists to clone extinct dinosaurs to create a zoo / theme park on a remote island off the coast of Central America. They are confident that their redundant systems have eliminated any risk. Of course, they are wrong; and everything soon goes tragically wrong.

It is a story of the consequence of hubris and the arrogance of man playing the part of God.

But it is not only a morality tale. It is an action story and an adventure story and a horror story and a monster story and a story of corporate espionage. Chrichton - a former MD - goes to great lengths to make the science plausible, even if we are unlikely to resurrect extinct creatures any time soon in this world.

If the book has a weakness, it is the single-dimensional characters; but this did not bother me. The dinosaurs are the stars here.

As the climax approached, I felt the fear and the stress, and the danger experienced by both heroes and villains as the dinosaurs closed in on them. I related to Alan and Ellie and Malcolm and Tim and Lex and Hammond and their approach to the project.

Spielberg made dinosaurs a cultural phenomenon; but he would not have done so without this book.

CruelIntentions"Cruel Intentions: The 90s Musical" is a play based on a movie I never saw, which is based on a book I never read. I did not know what to expect.

In preparation to see the live show at the Chopin Theatre Saturday evening, I watched the 1999 movie on Friday. I was underwhelmed by the campy dialogue and mediocre acting, despite the presence of stars Reese Witherspoon and Sarah Michelle Gellar and semi-star Ryan Phillipe.

But the things that brought down the movie worked in the live production. The musical version took itself far less seriously than the film, making the campy dialogue seem more appropriate, often gaining an audience laugh where the same line inspired an eye roll while watching the movie.

"Cruel Intentions" is the story of Sebastian Valmont and Kathryn Merteuil – entitled step-siblings enrolled at an exclusive prep school in Manhattan. They are so privileged and amoral that they place a bet on whether Sebastian can deflower the virginal daughter of the school's new headmaster.

Manipulation, false promises, and general sociopathy ensue; but all this is interrupted periodically by cast members bursting into hit songs from the 1990s. In the stage version, the plot takes a back seat to the music. Feeling confused or angsty? Sing REM's "Losing My Religion"; Feeling sexy? Belt out Marcy Playground's "Sex and Candy"; a little self-hate can be expressed with a raucous rendition of Garbage's "I'm Only Happy When It Rains"; Use the Back Street Boys' "I Want it That Way" to flirt. The lyrics do not always fit the situation exactly, but the mood does. And somehow it works.

It works because the cast has fun with it. And so did I.


Java is a popular language for developing applications on a variety of platforms. In order to create applications, you must first install Java on your machine or virtual machine. This article will walk you through the steps to install Java on Windows 10 or 11.

Is Java Already Installed?

You can test whether Java is currently by opening a command prompt, typing "java -version", and pressing ENTER.

If Java is installed, information about the current Java version will display. If Java is not installed, you will see a message similar to the following:

'java' is not recognized as an internal or external command, operable program or batch file.

A Note About Versions

You can choose from a number of available versions of Java. Generally, I recommend installing the latest Long Term Support ("LTS") version of Java. You may want to install a more recent non-LTS version of Java if you require a feature that is only available in that version. Also, the application on which you are working may require a specific version of Java.

As of this writing, Java 18 is the most recent version of Java, but it is not LTS. The available LTS versions are Java 8, 11, and 17.

This article describes the current LTS versions of Java.

Download the installation Executable

To download the installation files, navigate to https://www.oracle.com/java/technologies/downloads/. This page is shown in Fig. 1.

Fig. 1

In the center of the page are tabs for "Java 18" and "Java 17", as shown in Fig. 2.

Fig. 2

Currently, Java 18 is selected, so I will select "Java 17" because I want the LTS version. The "Java 17" tab is shown in Fig. 3.

Fig. 3

Lower on the page are tabs for different operating systems (Linux, macOS, and Windows), as shown in Fig. 4.

Fig. 4

Currently, Linux is selected; but I want to install this on Windows, so I will click the Windows tab. The Windows tab is shown in Fig. 5.

Fig. 5

NOTE: As of this writing, you navigate directly to the Java 17 Windows tab with the following URL: https://www.oracle.com/java/technologies/downloads/#jdk17-windows

The tab lists the available downloads relevant to Windows developers for Java 17.

Click jdk-17_windows-x64_bin.exe to begin downloading it.

Install It!

When the exe file finishes downloading, click the file to launch the install wizard.

The Installation Wizard displays, as shown in Fig. 6.

Fig. 6

Click the [Next>] button to advance to the next page of the Wizard, as shown in Fig. 7.

Fig. 7

If desired, click the [Change…] button to change the folder in which Java is installed. Usually, there is no reason for doing this.

Click the [Next] button to begin installing Java.

When installation completes, a confirmation dialog displays, as shown in Fig. 8.

Fig. 8

Click the [Close] button to close the Installation Wizard.

Verify Installation

After installing Java, it is a good idea to verify that it was installed correctly. The simplest way to do this is to open a command prompt, type "java -version", and press ENTER.

If Java is installed, information about the current Java version will display. If Java is not installed, you will see a message similar to the following:

'java' is not recognized as an internal or external command, operable program or batch file.

Note that you must open this command prompt after installing Java. If you opened the prompt before installation, it will not know that Java is installed.


In this article, I showed you how to install the latest LTS version of Java on your Windows machine.


By default, Azure App Services will not enforce any authorization for your Web Apps. You can implement authorization within your code, or you can configure an Identity Provider to perform authentication and authorization for you. In this article, I will walk you through the process of configuring Azure Active Directory as an identity provider. This will force anyone to log in with an Account in or registered in Azure Active Directory before accessing your website.

Register Identity Provider

The first step after you create your web app is to register an Identity provider.

Navigate to the App Service, as shown in Fig. 1.

Fig. 1

Select "Authentication" from the left menu to open the Authentication blade, as shown in Fig. 2.

Fig. 2

A new app will contain no Identity Providers. Click the [Add identity provider] button (Fig. 3) to open the "Add an identity provider" dialog, as shown in Fig. 4.

Fig. 3

Fig. 4

Completing this dialog will create a new App Registration in Azure Active Directory. From the "Identity provider" dropdown, select "Microsoft". The rest of the dialog will display prompts related to this provider, as shown in Fig. 5.

Fig. 5

At the "App registration type" prompt, select the "Create new app registration" radio button.

At the "Name" prompt, enter a unique name for the app registration. This will default to the name of your web app.

At the "Supported account types" prompt, you can choose to restrict access to only accounts in the current Active Directory tenant, to accounts in this and other tenants, and/or to personal accounts registered with Active Directory.

At the "Restrict access" prompt, select the "Require authentication" radio button.

The "Unauthenticated requests" prompt allows you to select the HTTP response returned when a user fails to authenticate. Most of these are appropriate for APIs. For a website, select the "HTTP 302" radio button.

Click the [Add] button to create a new App Registration in Azure Active Directory and return to the "Authentication" blade, as shown in Fig. 6.

Fig. 6

You should now see your newly created Identity Provider listed.

Grant access to roles

After registering your application, the next step is to grant access to specific users or roles within your app. By default, each App Service contains a couple of dozen roles. Adding an account to a role permits them to perform certain activities, such as viewing or updating your site.

To assign an account to a role, click the [Access control (IAM)] button (Fig. 7) in the left menu to open the "Access control (IAM)" blade, as shown in Fig. 8.

Fig. 7

Fig. 8

On the "Access control (IAM)" blade, click the [Add role assignment] button (Fig. 9) to open the "Add role assignment" page, as shown in Fig. 10.

Fig. 9

Fig. 10

On the "Role" tab, select the "Reader" role; then, click the [Next] button to advance to the "Members" tab, as shown in Fig. 11.

Fig. 11

Click the "Select members" link (Fig. 12) to open the "Select members" dialog, as shown in Fig. 13.

Fig. 12

Fig. 13

Search for an Active Directory account, as shown in Fig. 14 and 15.

Fig. 14

Fig. 15

Click the [Select] button to add this account to the "Reader" role. You will return to the "Add role assignment" page, as shown in Fig. 16. The account will now be listed under "Members".

Fig. 16

Click the [Review + assign] button to advance to the "Review + assign" tab, as shown in Fig. 17.

Fig. 17

Click the [Review + assign] button to save your changes.


In this article, you learned to configure Azure Active Directory as an Identity Provider for an Azure Web App. The steps above will create a new App Registration, which you can view from the "App Registration" blade of Azure Active Directory, as shown in Fig. 18.

Fig. 18

You have the option to create and configure the App Registration yourself; but the steps describe here take care of much of the configuration for you.


You can use Visual Studio Code to create applications in a number of languages. Many of those applications can run in Microsoft Azure App Services. This article will show you how to deploy a web application from Visual Code to an Azure App Service.

## Install VS Code Azure App Service Extension

Before you begin deployment, you must install the Azure App Service Extension. Click the Extensions icon (Fig. 1) in the left sidebar and search for the Azure App Service extension from Microsoft, as shown in Fig. 2.

Fig. 1

Fig. 2

If this extension is not yet installed, a [Publish] button will display. Click this button to install it.

Create a Web App

You can create a web app using ASP.NET, ASP.NET Core, Java, Ruby, Node.js, PHP, or Python. Visual Studio Code has extensions to support each of these. The language and framework are not relevant to this article, as the steps are the same.

Create a New Azure App Service

Before you deploy your code, you will need to Create a New Azure App Service to Host your Web App.

With your web application code open, click the Azure icon (Fig. 3) in the left sidebar and expand the Azure subscription to which you want to deploy and the "App Services" group within that subscription, as shown in Fig. 4.

Fig. 3

Fig. 4

You will need an Azure Web App to host your code. If you have not yet created a Web App, you can create one now by right-clicking the "App Services" node and selecting "Create New Web App.." from the context menu, as shown in Fig. 5.

Fig. 5

Enter a globally unique name for this Web App, as shown in Fig. 6, and press ENTER.

Fig. 6

Select the runtime stack from the list of supported stacks and press ENTER. In Fig. 7, I selected Node 16 LTS because I wrote my application in Node. The language in which you wrote your app will determine your selection.

Fig. 7

At the "Select a pricing tier" prompt, select the tier to which you want to deploy your Web App, as shown in Fig. 8. More powerful tiers will be more robust and reliable, but more expensive.

Fig. 8

After a few minutes, an Empty Web App is created. You can now deploy your application to this Web App by clicking the [Deploy] button on the confirmation dialog, as shown in Fig. 9.

Deploy App to Azure App Service

You can now deploy your application to this Web App by clicking the [Deploy] button on the confirmation dialog, as shown in Fig. 9.

Fig. 9

The prompt in Fig. 10 displays.

Fig. 10

Select the folder containing your application's code from the list or click browse to find it on your computer.

After you select the code location, the warning in Fig. 11 displays.

Fig. 11

Click the [Deploy] button to begin deploying your code to the Azure App Service.

You will receive the confirmation message shown in Fig. 12 when the deployment succeeds.

Fig. 12

You can now browse your web site or manage the App Service in the Azure Portal.


In this article, I showed how to deploy a web application quickly and easily from Visual Studio Code.

Episode 716

Darryl Hogan on Accelerating Technologies for Nonprofits

Darryl Hogan discusses how technologists can help nonprofit organizations with their technical issues, such as building applications, databases, web sites, or infrastructure.

With "The Final Cut", Michael Dobbs concludes his "House of Cards" trilogy, and he does so in dramatic fashion.

This story begins with a flashback to a young Francis stationed in Cyprus in the British Army, assigned to fight the Cypriots in their battle for independence. Urquhart committed and covered up a war crime that no one has since discovered. Decades later, Urquhart faces a new challenge in Cyprus, which gives him the opportunity to rise above the public's criticism and save the day. He is decisive and forceful and determined to achieve victory at all costs; and he knows that he will be hailed a hero if he succeeds.

The series tells of the rise to power of British Prime Minister Francis Urquhart. TFC reveals what happens when Urquhart reaches the top and the world tires of him. Urquhart has been PM for 10 years and he is poised to eclipse Margaret Thatcher's tenure, but his popularity is declining. The public is clamoring for new blood and fresh ideas, while Francis is losing the support of many in his cabinet. Dobbs paints a picture of a ruthless man, terrified of losing his power. FU knows only politics and has no interests outside politics. He knows he will be lost if he loses the power he has built. "The Final Cut" is the story of a master Machiavellian, who rose to power by exploiting and destroying others and must use those same vile skills to stay on top. The PM always seems to come out on top at the expense of his rivals. Dobbs keeps us wondering if that will be the case this time.

This is a strong finish to an excellent trilogy.


The Microsoft Edge web browser allows you to create and manage multiple profiles on the same machine.

Using multiple profiles, you can open browser sessions on the same machine that are associated with different users or different accounts. This can be useful to keep separate your work and personal browser settings and your company settings separate from each customer's environment.

Each profile is associated with an email address. You can create a new email address at https://outlook.com

Creating a New Profile

To create a new profile, open Microsoft Edge and click the profile icon (Fig. 1) in the top right corner of the browser to launch the menu shown in Fig. 2. My profile icon has a photo of me, but yours may have your initials. You configured a default profile the first time you launched Microsoft Edge after installing it on this machine.

Fig. 1

Fig. 2

Click the [Add profile] menu option to open the "Add a profile" blade, as shown in Fig. 3.

Fig. 3

The "Welcome to Microsoft Edge" screen displays, as shown in Fig. 4.

Fig. 4

Click the [Sign in to sync data] button to display, the "Let's get you signed in" dialog, as shown in Fig. 5.

Fig. 5

Enter your email address and click the [Sign In] button to display the "Enter password" dialog, as shown in Fig. 6.

Fig. 6

Enter the password associated with this email and click the [Sign In] button to display the "Help us protect your account" dialog, as shown in Fig. 7.

Fig. 7

Re-enter your email address and click the [Next] button to display the "Enter your security code" dialog, as shown in Fig. 8; then check your email for a message with a 6-digit code.

Fig. 8

Enter the 6-digit code from the email and click the [Next] button to display the confirmation dialog, as shown in Fig. 9.

Fig. 9

Click the [OK] button to close this dialog and display the "Windows Security" dialog, as shown in Fig. 10.

Fig. 10

Enter the PIN you use to unlock this Windows workstation. click the [OK] button to display the "Add details" dialog, as shown in Fig. 11.

Fig. 11

Enter your name, birth date, and country in the appropriate fields and click the [Next] button to display the "Please confirm your age" dialog, as shown in Fig. 12.

Fig. 12

Click the [Next] button if your birth date is displayed correctly and click the [Next] button to display a confirmation dialog, as shown in Fig. 13. If your birth date is not displayed correctly, click the [Back] button and correct it.

Fig. 13

Click the [Confirm and start browsing] button to begin using this new profile.

Now that you have create the profile, you can switch between profiles by clicking the profile icon at the top right of the Edge browser, as shown in Fig. 14.

Fig. 14

Managing a Profile

You can make changes to your profiles from the Edge Settings page. Open the Edge Settings page by clicking the Ellipsis in the top right corner of the browser and selecting "Settings" from the dropdown menu, as shown in Fig. 15.

Fig. 15

The "Settings" page displays, as shown in Fig. 16.

Fig. 16

If the "Profiles" tab is not selected, select it from the left sidebar. The current profile is highlighted, but you can view your other profiles in the "More profiles" section below. Click the [Switch] button next to one of these profiles to view the settings associated with it.

To modify profile settings, click the Ellipsis next to the profile and select "Edit" from the dropdown menu, as shown in Fig. 17.

Fig. 17

The "Edit profile" dialog displays, as shown in Fig. 18.

Fig. 18

Give this profile a more descriptive name, making it easy to identify from a list of your profiles.

By default, this profile displays only your initials. To upload your own picture, click the "Change picture" link, which displays the dialog shown in Fig. 19.

Fig. 19

Click the "Add a photo" link and select a photo from your local drive. The photo will display in the Drop Zone, as shown in Fig. 20.

Fig. 20

Use the controls to zoom in and out and position the photo as desired. Click the [Save] button to commit this photo.

The confirmation dialog shown in Fig. 21 displays.

Fig. 21

Click the [Close] button when finished.

Deleting a Profile

If you decide you no longer need a profile, you can delete it from the Microsoft Edge Settings page. Sometimes, I create a profile for the purpose of using Single Sign On in with a customer's credentials and I no longer need this profile when my work with that customer concludes.

Open the Edge Settings page by clicking the Ellipsis in the top right corner of the browser and selecting "Settings" from the dropdown menu, as shown in Fig. 22.

Fig. 22

The "Settings" page displays, as shown in Fig. 23.

np23-ProfileSettings - Copy
Fig. 23

If the "Profiles" tab is not selected, select it from the left sidebar. The current profile is highlighted, but you can view your other profiles in the "More profiles" section below. Click the [Switch] button next to one of these profiles to view the settings associated with it.

To delete a profile, click the Ellipsis next to the profile and select "Delete" from the dropdown menu, as shown in Fig. 24.

Fig. 24


In this article, you learned how to create a new profile in Microsoft Edge, manage that profile, and delete that profile.

GCast 129:

Using the Microsoft Docker Extension for Visual Studio Code

Learn how to use the Microsoft Docker extension for Visual Studio Code to make your Docker development more efficient.

Jeff Fritz on .NET Conf

Comments [0]

Episode 715

Jeff Fritz on .NET Conf

Jeff Fritz is preparing for .NET Conf - a 3-day online conference scheduled in November, considiing with the release of .NET 7. He talks about the content of the conference, what goes into putting it on, and how you can get involved.

FabulousThunderbirdsThe Fabulous Thunderbirds know the blues.

Monday evening at the City Winery, they delighted the audience for two hours, moving seamlessly from jump blues to boogie-woogie to rock & roll to slow burn songs like Charles Brown's "Black Night" to funky songs like their 1980s song "Wrap It Up".

The band formed nearly five decades ago in Austin, TX. Lead vocalist Kim Wilson remains the only constant member, but the current lineup still brings strong energy and technical chops to their performance. Bob Welsh's energetic solo on "Slow Down" - a Larry Williams song made famous by The Beatles - was outstanding, as were Jerry Weldon's saxophone solos and Dean Shot's guitar solos on multiple songs.

In all those years, their only US Top-40 hit was "Tuff Enuff", which peaked at Number 10 in 1986 and which they played as the penultimate song of the evening. But the group continued to tour, and it is their live performances that drive the band and their fans. I saw them at a festival in Detroit in 1989 with Jimmie Vaughn on guitar. The names and faces have changed but the energy remains high.

The club Monday night was barely half full, but those who attended enjoyed it. A couple at the table next to mine appeared to be in their 70s or 80s but spent much of the evening dancing.

The show's opening was delayed as Weldon had trouble locating the microphone for his sax; but it closed with a strong harmonica solo by Wilson that brought the audience to its feet.

More photos

HowieDayHowie Day has a beautiful voice, is an accomplished guitar player, and has written dozens of great songs. For many, that would be enough. But Day takes it a step further in his concerts.

Thursday night at City Winery, Day appeared on stage with only a guitar and a few switches at his feet. Frequently, he would record his voice or his guitar playing or the sound of him tapping on the exterior of his instrument; then, play back these recordings on a loop to create rich layers of music. At times, he would enhance the playback with a bit of reverb. We heard musical arrangements and harmony vocals as if he were not alone on stage.

Between songs, Howie chatted casually with the audience about his life and his music. He introduced the song "Disco" by telling us he recorded it in his parents' basement "which sounds sad, but I was seventeen at the time". He sang an alternate country music version of his song "Be There", entitled "Beer There", complete with a southern twang.

Highlights included "Be There", "Tree Tops", "Longest Night", and his biggest hit "Collide". Nearly every song was an original, but he mixed in U2's "One" and opened his encore set with Crowded House's "Don't Dream It's Over".

It was a show filled with more energy than one would expect from a singer/songwriter who specializes in ballads and love songs.

I have never seen anything quite like a Howie Day performance. I have seen many musicians backed by drum machines or pre-recorded instruments and I have even seen a few record a brief snippet before playing on loop as their own accompaniment; but I have never seen a musician layer so many levels of music simultaneously and create such a rich sound as I witnessed Thursday evening.

More photos

Episode 714

Michael Mishal on Reinforcement Learning

Michael Mishal describes how reinforcement learning can use rewards to solve complex artificial intelligence problems.

July 2022 Gratitudes

Comments [0]

Today I am grateful for all the good things about the United States and for the freedom to express my opinions on the bad things about it

Today I am grateful to watch fireworks displays around the city from my balcony.

Today I am grateful for groceries delivered to my door.

Today I am grateful to sleep much of yesterday while recovering and still be able to sleep last night

Today I am grateful to the friend who gave me a bunch of really nice furniture yesterday.

Today I am grateful to those who care about my health

Today I am grateful for a call from my brother and sister-in-law in Australia yesterday.

Today I am grateful to finally test negative for COVID

Today I am grateful for:
- a kickoff to the Fiscal Year with others in my organization
- having Zoe stay with me for a couple weeks

Today I am grateful for:
-my first visit to Nebraska
-hanging out last night with the Nebraska.Code speakers

Today I am grateful to deliver a keynote presentation at the Nebraska.Code conference yesterday

Today I am grateful to Ken and the organizers and volunteers that made Nebrasa.Code a great success!

Today I am grateful to see the Nitty Gritty Dirt Band in concert last night

Today I am grateful to go bike riding this weekend for the first time since getting sick weeks ago.

Today I am grateful:
- for dinner last night with Chris and his family
- to see an entertaining David Gray concert last night

Today I am grateful:
- to attend the Microsoft Inspire event with partners at the Aon Center yesterday
- for drinks and jazz with Thad last night

Today I am grateful for an unexpected visit from my son this week

Today I am grateful for 75 years of marriage for my Uncle Bill and Aunt Jean.

Today I am grateful for my first visit to the South Loop Farmers Market at Grant Park

Today I am grateful to see the Psychedelic Furs in concert last night.

Today I am grateful to catch up on sleep yesterday and last night.

Today I am grateful to work with my trainer this morning for the first time since I became sick last month.

Today I am grateful for online training resources.

Today I am grateful for an ice cream social  at the Aon Center yesterday.


Today I am grateful to experience Teatro Zinzanni last night in Chicago

Today I am grateful for my first visit to Second City in years.

Today I am grateful that my lingering COVID symptoms are nearly gone

Today I am grateful for a new (to me) kitchen table - the first one I have owned in over 8 years!

Today I am grateful to see the Jim Irsay collection and band at Navy Pier last night

Today I am grateful for dinner with a bunch of Microsoft folks in downtown Chicago last night.

Today I am grateful:
-to co-lead a Diversity & Inclusion workshop yesterday morning
-to attend the Windy City Smokeout with Josh yesterday afternoon
-to see Howie Day in concert last night

Today I am grateful for a return to Grand Rapids, MI for the first time in years.

Today I am grateful to speak at an excellent Beer City Code conference yesterday.

TeatroZinZanni-1I have been to circuses and concerts and restaurants and theater, and dinner theater and improv shows and drag shows.

Thursday night at the Cambria Hotel in Chicago's Theater District, I experienced Teatro ZinZanni, which combined all of these into a single evening performance.

I had heard good things about this show but an announcement that it would close in two days was the motivation I needed to buy Friday evening tickets.

At center stage was a cross-dressed oversexed giantess, who shamelessly teased and flirted with the audience, driving the show forward. He/she was funny and crass and over the top.

TeatroZinZanni-2But in between, we heard excellent singers backed by a top-rate band and jugglers and acrobats and trapeze artists. The trapeze artists were the most impressive to me.

In between these, cast members ran among the tables in elaborate costumes interacting with the audience.

In between these, we enjoyed a very good dinner.

I did not know what to expect, but the show entertained us greatly.

Teatro ZinZanni has left Chicago to begin a run on the west coast. But the theater will reopen with Cafe Zazou in September. I think I know what to expect from this show.

But who knows?

GCast 128:

Maintaining State with Docker Volumes

Docker containers are stateless by default, which means that, when one is destroyed, all data created after the container is lost. However, you can get around this limitation by attaching a volume to your container. This video shows you how to create and manage Docker volumes.

To access an Azure Key Vault secret from your code, you must register your key vault as an application.

The steps are:

  1. Create the key vault
  2. Register the application with Azure Active Directory
  3. Add a Client Secret to the App Registration
  4. Add an Access Policy to the Key Vault
  5. Set Environment Variables
  6. Write the code

Create the key vault

First, you need to create a Key Vault in which to store your secrets. For instructions on how to create a Key Vault, see this article.

Register the application with Azure Active Directory

After creating a Key Vault, register the Key Vault with Azure Active Directory.

This article shows how to do this.

For our purposes, the most important pieces of information from the Application Registration are the  Application ID, which is sometimes called the Client ID.

You can find this on the Azure Active Directory "App registrations" blade. Search for your App Registration by name, as shown in Fig. 1.

Fig. 1

Record the Display name, the Application (client) ID) and the Directory (tenant) ID. You will need these later.

Add a Client Secret to the App Registration

Next, you will need to create a Client Secret within your Application Registration.

Within the App Registration, click the [Certificates & secrets] button (Fig. 2) to open the "Certificates & secrets" blade, as shown in Fig. 3

Fig. 2

Fig. 3

To create a Client Secret, select the "Client secrets" tab and click the [New client secret] button (Fig. 4) to open the "Add a client secret" dialogue, as shown in Fig. 5.

Fig. 4

Fig. 5

At the "Description" field, enter a description of the secret (e.g., for which application are we generating a secret).

At the "Expires" dropdown, select how soon this secret will expire, requiring you to generate a new one.

When you finish completing the dialogue, click the [Add] button (Fig. 6) to return to the Application Registration" page, as shown in Fig. 7.

Fig. 6

Fig. 7

Your newly created secret will display in the list on the "Client secrets" tab. Copy and save the "Value" column. After you navigate away from this page, you will no longer be able to view the Value.

Add an Access Policy to the Key Vault

An Access Policy tells Azure which users, applications, and services have access to Azure Key Vault and what actions they can take on the information stored in Key Vault. After you have registered the application, you will need to create an Access Policy in Azure Key Vault, providing the Application Registration access to the key vault.

To add an Azure Key Vault Access Policy, navigate to the Azure Portal, log in, and open the Azure Key Vault, as shown in Fig. 2.

Fig. 8

Click the [Access policies] button (Fig. 3) in the left menu to display the "Access Policies" blade, as shown in Fig. 4.

Fig. 9

Fig. 10

Click the [Add Access Policy] button (Fig. 5) to display the "Add access policy" dialogue, as shown in Fig. 6.

Fig. 11

Fig. 12

This dialogue provides a number of templates which preselect permissions to access and manage keys, secrets, and certificates in this Azure Key Vault. If you like, you can select one of these, as shown in Fig. 7.

Fig. 13

Alternatively, you can specify each permission explicitly for keys, secrets, and certificates in this key vault. Fig. 8 shows how to select all permissions for managing secrets, which I will do for this demo.

When you have selected all the desired permissions, click the [Add] button (Fig. 8) to return to the "Add access policy" dialogue.

Fig. 14

The next step is to give these permissions to the Application Registration. Click the link next to "Select principal" to open the "Principal" dialogue, as shown in Fig. 9.

Fig. 15

Search for the Application Registration by display name, select the Registration from the list, as shown in Fig. 10 and click the [Select] button to close the "Principal" dialogue and return to the "Add Access Policy" dialogue, as shown in Fig. 11.

Fig. 16

Fig. 17

Finally, click the [Save] button (Fig. 12) to close the "Principal" dialogue and return to the "Access Policies" blade, as shown in Fig. 13. You will lose your changes if you fail to click the [Save] button before navigating

Fig. 18

Fig. 19

Set Environment Variables

The sample application below uses the DefaultAzureCredential class to authenticate the user. This class pulls information from the following environment variables:

  • AZURE_CLIENT_ID (from App Registration "Overview" blade)
  • AZURE_CLIENT_SECRET (from App Registration "Certificates & secrets" blade, "Value" field)
  • AZURE_TENANT_ID (from App Registration "Overview" blade)

The values for each of these fields were acquired in the steps above.

Write the code

In a .NET Core application, the following NuGet packages assist you when working with Azure Key Vault.

  • Azure.Security.KeyVault.Secret
  • Azure.Identity

Create a new Console Application in Visual Studio and install the Azure.Security.KeyVault.Secrets and Azure.Identity NuGet packages.

As stated above, we can use the DefaultAzureCredential class to represent the principal used to make calls to our Azure Key Vault and the information (AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, and AZURE_TENANT_ID) are stored in environment variables.

We create a DefaultAzureCredential object with the following code:

var credentials = new DefaultAzureCredential();

Then, we use this object to create a SecretClient object, as in the code below.

secretClient = new SecretClient(new Uri(keyVaultUri), credentials);

The SecretClient object provides methods to access and manage our Key Vault secrets.

For instance, we can get information about all the secrets in our Key

The following code retrieves information on all secrets in the Key Vault and lists the name, value, and content type of each

Console.WriteLine("All Secrets:");
var allSecrets = secretClient.GetPropertiesOfSecrets();
foreach (var secret in allSecrets)
     var secretValue = secretClient.GetSecret(secret.Name);
     Console.WriteLine($"{secret.Name} | {secretValue.Value.Value} | {secretValue.Value.Properties.ContentType}");

Other SecretClient methods allow us to get, set, or delete a Secret, as shown in the following code snippets:

await secretClient.SetSecretAsync(setSecretName, setSecretValue);
var secret = secretClient.GetSecret(setSecretName);
var operation = secretClient.StartDeleteSecret(deleteSecretName);

By default, Azure Key Vault supports soft delete, meaning that a deleted object can be retrieved for a given period after deletion (90 days, by default).
To permanently delete a secret prior to this, we can issue a purge command after the soft delete has completed. We can determine when the soft delete has completed by querying the Boolean DeleteSecretOperation.HasCompleted property.

if (operation.HasCompleted)

Below is the full code of a .NET Core Console application

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace testKeyVaultConsoleApp
     internal class Program
         const string KEYVALUTNAME = "dgtestkeyvault"; // Set this to the name of your key vault
         static string keyVaultUri = $"https://{KEYVALUTNAME}.vault.azure.net";

        static SecretClient secretClient = null;

        static async Task Main(string[] args)
             var credentials = new DefaultAzureCredential();
             secretClient = new SecretClient(new Uri(KEYVAULTURI), credentials);


            Console.Write("Input the Secret name to set (ENTER to skip):");
             var setSecretName = Console.ReadLine();
             if (setSecretName != "")
                 Console.Write("Input the Secret value to set:");
                 var setSecretValue = Console.ReadLine();

                Console.WriteLine("Setting secret...");
                 await secretClient.SetSecretAsync(setSecretName, setSecretValue);
                 Console.WriteLine($"Secret {setSecretName} set to {setSecretValue}!");

                // Set content type
                 var secret = secretClient.GetSecret(setSecretName);
                 secret.Value.Properties.ContentType = "Demo Type";

            Console.Write("Input a Secret Name to soft delete (ENTER to skip):");
             var deleteSecretName = Console.ReadLine();
             if (deleteSecretName != "")
                 var operation = secretClient.StartDeleteSecret(deleteSecretName);
                 Console.Write($"Deleting secret {deleteSecretName}...");
                 while (!operation.HasCompleted)
                 Console.WriteLine($"Secret {deleteSecretName} deleted!");

            Console.Write("Input a Secret Name to permanently delete (ENTER to skip):");
             var purgeSecretName = Console.ReadLine();
             if (purgeSecretName != "")
                 var operation = secretClient.StartDeleteSecret(purgeSecretName);
                 Console.Write($"Soft deleting secret {purgeSecretName}...");
                 while (!operation.HasCompleted)
                 Console.WriteLine($"Secret {purgeSecretName} deleted!");
                 Console.WriteLine($"Secret {purgeSecretName} purged!");



        private static void ListAllSecrets()
             Console.WriteLine("All Secrets:");
             var allSecrets = secretClient.GetPropertiesOfSecrets();
             foreach (var secret in allSecrets)
                 var secretValue = secretClient.GetSecret(secret.Name);
                 Console.WriteLine($"{secret.Name} | {secretValue.Value.Value} | {secretValue.Value.Properties.ContentType}");


You can find the code here.

NOTE: Visual Studio reads Environment Variables on launch, so it may be necessary to restart Visual Studio after you set the environment variables.


In this article, you learned how to create a Key Vault and manage its secrets from a .NET Console application.

Episode 713

James McKee on Application Security vs Developer Security

Security Advocate James McKee describes how we can increase cybersecurity by building security into the application development process.

"The Fires of Heaven" is Robert Jordan's fifth book in "The Wheel of Time" series. Despite a plethora of characters introduced in the first four novels, this book is very much the story of Rand al'Thor. Rand is the Dragon Reborn, the foretold reincarnation of Lews Therin Telamon - a warrior king from thousands of years ago, who is destined to lead the forces of light against those of darkness in the upcoming final battle. Rand gathers and command his armies, battles dark friends, and feels his sanity slipping away as Lews Therin's thought intrude upon his mind.

Jordan is often criticized (sometimes by me) for the slow pace of the series. But the passage of time makes Rand's gradual transformation from naive shepherd to warrior king more plausible.

Two other characters grow considerably in this volume: Mat tries to run from his responsibilities but repeatedly rises to the challenges set before him; and Morgaine sacrifices her pride and more to do what is right.

Other significant developments in TFOH:

  • Villainess Lanfear's obsession with Rand and Lews Theron finally erupts into a violent confrontation
  • An ancient warrior woman is released to the real world after centuries trapped in a dream world

Perrin is notably missing from this book - presumably resting from his heroic actions in the previous novel and celebrating his honeymoon.

The action accelerates near the end of this book: major characters are killed, and others seek vengeance against their murderers. The switching perspectives in the final chapters show the same action from different points of view, giving a frantic pace to the narration.

"The Fires of Heaven" starts slowly but is saved by a strong finish.

Psychedelic FursSome things stay the same and sometimes that is a very good thing. Brothers Richard and Tim Butler formed The Psychedelic Furs in the late 1970s and they form the core of the band today. Saxophonist Mars Williams joined in 1983 and remains with the band.

Saturday night, they were joined by Amanda Kramer (keyboards), Rich Good (guitar), and Zack Alford (drums) to the delight of thousands of fans at the Aragon Ballroom in Chicago's Uptown neighborhood.

The evening began with a set by LA-based band X, a group I remember from my college days in the early 1980s. Back then, they were primarily a punk band, but they showed greater range on this night than I remember from their LPs in my dorm room. In addition to their earlier hardcore music, we heard a mix of rockabilly and alternative rock. X maintained even more consistency over the decades than the Furs. Their founding members - D. J. Bonebrake, Exene Cervenka, John Doe, and Billy Zoom still perform together and still know how to rock hard.

XListening to X primed the audience for The Psychedelic Furs, who opened by launching into the frantic "Mr. Jones", which got the crowd bouncing. Of course, the biggest cheers came when they played their biggest hits, such as "Pretty in Pink", "Love My Way", "Heaven", and "Heartbreak Beat". These songs were recorded and released in the 1980s, but they sound fresh today. Vocalist Richard Butler's voice remains unchanged over the decades and the rest of the band retains a high energy when playing these songs for the thousandth time. Thanks in large part to Richard’s vocals, the live performance retains the technical quality of their recording sessions.

The Psychedelic Furs were part of a strong group of British synthpop bands that emerged after the punk movement of the 1970s. They have had more staying power than most of their peers, thanks to strong melodies and arrangements and a commitment to touring for the past decades.

We nearly saw a second show when an unstable patron tripped and fell, knocking heads with a woman in the front row of the balcony, nearly sending both of them over the railing. Thankfully, no one was seriously injured.

And no one went home disappointed from this excellent, high-energy show.

Registering an application in Azure Active Directory (AAD) allows the Microsoft Identity Platform to manage access to that application. Registration establishes trust between the application and the client.

To register an application, navigate to the Azure Portal, log in, and select the [Azure Active Directory] button (Fig. 1) in the left menu (or search for Azure Active Directory in the search box at the top of the portal.

Fig. 1

The Azure Active Directory "Overview" blade displays, as shown in Fig. 2.

Fig. 2

Click the [App registrations] button (Fig. 3) in the left menu to display the "App registrations" blade, as shown in Fig. 4.

Fig. 3

Fig. 4

Click the [New registration] button (Fig. 5) to display the "Register an application" dialogue, as shown in Fig. 6.

Fig. 5

Fig. 6

At the "Name" field, enter a name for this registration. If I am registering one application, I like to include the name of that application, followed by "AppReg". Whatever you choose, it should be easily identifiable, so you can pick it out of a list of app registrations.

At the "Supported account types" prompt, select the appropriate radio button depending on where the login accounts of the client reside. You can accept logins from only the current Azure Active Directory, from this and other Active Directories, from Active Directories plus non-AAD Microsoft accounts, and only from non-AAD Microsoft accounts.

The "Redirect URI" section is optional. It is most useful in web applications to indicate to which page the system redirects a user after a successful authentication. If you are unsure, you can leave this empty and configure it later.

The "Service Tree ID" field is only relevant if you are using the Microsoft Service Tree service, which allows you to relate multiple apps and services, making them more easily searchable by your users.

If you have a Service Tree account, enter the ID in this field.

After completing the dialogue, click the [Register] button to register the application. It typically takes less than a minute to register an application.

After the registration is complete, the app registration page displays, as shown in Fig. 7.

Fig. 7

The next steps depend on the type of application you are registering. I will cover some scenarios in future articles; but you can get a head start by clicking the appropriate link under "Build your application with the Microsoft identity platform".

Azure Key Vault is an ideal place to securely store, manage, and retrieve secrets used by your application or service.

A secret is a name/value pair in which the value is any string or serialized object of length up to 25k bytes. We retrieve a secret's value by its name. Secret values are encrypted by default.

In this article, I will show how to add a secret to a Key Vault.

Navigate to the Azure Portal, sign in, and open the Azure Key Vault. If you do not have a Key Vault, see this article, for instructions on how to create one.

The Key Vault "Overview" blade displays, as shown in Fig. 1

Fig. 1

Click the [Secrets] button (Fig. 2) in the left menu to display the "Secrets" blade, as shown in Fig. 3

Fig. 2

Fig. 3

On the "Secrets" blade, click the [Generate/Import] button (Fig. 4) to display the "Create a secret" dialog, as shown in Fig. 5.

Fig. 4

Fig. 5

At the "Uploads" dropdown, select "Manual".

At the "Name" field, enter a name for your secret.

At the "Value" field, enter the value of your secret. This can be any string. It will not display as you type.

Optionally, you can select a range in which the secret is valid. To do so, select either or both of the checkboxes ("Set activation date" and "End activation date"). Fields will display, allowing you to enter the date, time, and time zone for the earliest and/or latest time that the secret can be accessed.

If you do not want to make the secret available yet, but have not yet decided on which date it will be available, you can toggle the "Enabled" switch to "No" and change it to "Yes" when you decide the secret should be available.

If you wish, you can add one or more tags to the secret. Tags are name/value pairs that provide metadata for an Azure resource. They don’t affect the resource, but they can be useful when grouping them together on reports – for determining which resources belong to which departments, for example.

After completing this dialog, click the [Create] button (Fig. 6) to add the Secret to the Key Vault. The "Secrets" blade will display again with the newly-added secret listed, as shown in Fig. 7.

Fig. 6

Fig. 7

You can now use this secret in code or in a variety of Azure services.

Azure Key Vault is a service that provides a secure way to store and manage secrets, encryption keys, and certificates.

You can access it through the portal, via PowerShell or Azure CLI, and using a variety of SDKs.

Before using this service, you must first create an Azure Key Vault in your subscription. This article describes how to do this.

Navigate to the Azure Portal and sign in.

Click the [Create a resource] button (Fig. 1); then, search for and select "Key Vault", as shown in Fig. 2.

Fig. 1

Fig. 2

A description of the Azure Key Vault displays, as shown in Fig. 3.

Fig. 3

Click the [Create] button to begin the creation process. The "Create a Key Vault" blade displays with the "Basics" tab selected, as shown in Fig. 4

Fig. 4

At the "Subscription" dropdown, select the subscription in which you want to store this Key Vault. Most users will have only one subscription.

At the "Resource group" field either select an existing resource group or create a new one for this Key Vault.

At the "Key vault name" field, enter a unique name for this Key Vault.

At the Region, select an Azure region into which to deploy this Key Vault. It should be physically close to the services and applications that will access it.

At the "Pricing Tier" prompt, select either "Standard" or "Premium". The main difference is that the Premium tier supports keys protected by a Hardware Security Model (HSM).

When a Key Vault is deleted, Azure retains it for a period before permanently "purging" it in case you wish to restore the Key Vault. This is known as a "soft delete". In the "Recover options" section, you can set the number of days between the deletion and the permanent purge. You can also use the radio buttons to allow or disallow authorized users to manually purge a key vault before the retention period ends.

To create a Key Vault, it is only necessary to complete the information on the "Basics" tab. So, you can click the [Review + Create] button to advance to the "Review + Create" tab. However, you may wish to further customize the key vault, so I will review the other tabs. You can switch between tabs by either clicking the [Next] and [Previous] buttons at the bottom or by selecting the name of the tab at the top.

Fig. 5 shows the "Access Policy" tab.

Fig. 5

Here you can give ARM templates and VM deployments, as well Disk Encryption access to the information in this Key Vault. You can also give specific permissions to specific users.

Fig. 6 shows the "Networking" tab.

Fig. 6

On this tab, you can restrict access to a given set of private networks.

Fig. 7 shows the "Tags" tab.

Fig. 7

Tags are name/value pairs that provide metadata for an Azure resource. They don’t affect the resource, but they can be useful when grouping them together on reports – for determining which resources belong to which departments, for example.

Fig. 8 shows the "Review + Create" tab.

Fig. 8

Correct any errors reported. When all settings are validated, click the [Review + Create] button (Fig. 9) to begin creating the Key Vault.

Fig. 9

It takes a few seconds to create and deploy a Key Vault. Upon completion, the confirmation message shown in Fig. 10 displays.

Fig. 10

Click the [Go to resource] button (Fig. 11) to display the Key Vault's "Overview" blade, as shown inf Fig. 12.

Fig. 11

Fig. 12

You are now ready to store secrets, keys, and certificates in your Key Vault, which I will cover in a future article.

Episode 712

Drew Brown on The New Technology Employment Contract

Drew Brown is the CIO of Union Bank & Trust. He discusses the way the workplace has changed in the last few years and what this means for the future.

With "Paddington Marches On", I am now halfway through the twelve collections of short stories that Michael Bond published about the talking bear Paddington Brown.

Paddington continues to get in trouble, despite his best intentions. And, in each case, things work themselves out for the best. Mr. Bond has found a formula and it works. We keep reading because we like Paddington and we care about him and we want him to succeed, even though we know he always will.

As a bonus, I learned a bit about the sport of cricket!

And there is a nice surprise for Paddington and for the reader at the end of the last story!

"Paddington At Large" is Michael Bond's fifth collection of stories about Paddington the bear, who was discovered by the Brown family in London's Paddington Station and became a member of their family.

This anthology is less cohesive than the last two; its stories are only loosely connected, but all involve the antics of the talking bear and the trouble he gets into and out of while trying to do good.

Of the seven tales contained herein, my favourite was "Paddington Hits the Jackpot" in which the young bear appears on a television game show and outsmarts the host by explaining why each of his answers is correct, despite what is written on the host's card.

In other stories,

Paddington has a disastrous time mowing the lawn of his mean neighbor Mr. Curry;

At a concert in the park, Paddington is annoyed to learn that one of the symphonies is "unfinished"

Paddington confronts a repairman in the Brown home

A recipe for toffee proves too much for a young bear to handle

Paddington causes chaos in a department store

A local playwright recruits Paddington for his stage production in which the bear saves the day

Each story is short and each one made me smile.

Usually, we need to have the right answers to build the right solution. But, to get these answers, we need to ask the right questions.

The Microsoft Azure Well-Architected Framework helps us to frame those questions.

The framework divides Azure concepts into five categories, which they refer to as "pillars". Just as physical pillars that can hold up a physical structure, these pillars hold up the design of your cloud application. Each pillar covers a broad area of web architecture and helps you formulate questions and answers about that area. The pillars (in no particular order) are:

  • Cost Optimization
  • Operational Excellence
  • Performance Efficiency
  • Reliability
  • Security

Let's briefly discuss what each one covers

Cost Optimization

Azure resources can provide, but they cost money. This pillar helps you maximize the value for the price you are paying: Are you getting sufficient value for money outlayed and are there ways to save money, while still meeting your needs?

Some ways you can increase your cost optimization are:

  • Look for wasted resources, such as services that are running during times they are not used
  • Disks that are not attached to a Virtual Machine
  • Deploying more capacity than a service needs

Monitoring can help you discover these inefficiencies, as can Azure Advisor.


Reliability is the ability to keep an application or service running, to anticipate failures, and to have a plan to recover quickly from those failures.

Typically, a cloud application focuses reliability efforts on the ability to quickly recover from failure, rather than preventing failure. Often, we quantify a reliability target in terms of a Service Level Agreement (SLA), which is the promised percentage of time our service will be available. For example, our SLA may promise 99.99% uptime (often referred to as "4 9's), which promises the application will be down only .01% of the time, which equates to less than an hour per year. However, reliability can also refer to maintaining a level of performance in terms of speed and features. Degradation of either of these decreases reliability.

We can increase reliability by providing redundancy to reduce a single point of failure, failovers in case of trouble, and

Despite your best efforts, it is likely that your system may go down unexpectedly and that you may lose some data. Therefore, it is essential that you have a detailed and tested plan to restore both the system and the data.

Azure takes care of some of this for us via such things as Update Domains, Availability Sets, Availability Zones, and built-in backup tools; but it is still up to us to opt into these services and configure them.

It is important to recognize that our application may be dependent on other services, so we need to consider the reliability of those services when considering the SLA of our app.

Operational Excellence

Operational Excellence refers to the ability to deploy an application reliably and to verify that deployment. Automated deployment is your friend here. Infrastructure as Code tools, such as ARM templates allow you to declare the state of an environment after a deployment. Automated build tools, such as Continuous Integration and Continuous Deployment pipelines in GitHub and Azure DevOps allow you to consistently build, test, and deploy your code to an environment in a repeatable way. Using these tools, we can automate the initial deployment of our application and manage subsequent releases, even rolling back a release if something goes wrong.

Testing is crucial to ensure quality before deploying code. Monitoring can assure that it remains in a good state and alerts you when it is not.

These processes can and should be automated as much as possible to simplify assurance of Operational Excellence.


Security is an important pillar when architecting any application, whether or not it is in Azure. It is also one of the more complex topics in software development.

A key principle to keep in mind when designing your application is "Zero Trust" - never assume you can trust the person or account accessing your application.

A good approach is to recognize the layers that a user must get through to access your data and to add protection at each layer.

Azure implements some security for you by default, such as encryption of data in storage accounts. But you must be aware of potential areas of attack and defend against them. Tools like Azure AD Single Sign, Privileged Identity Management, and Azure Key Vault allow you to implement a secure solution.

Performance efficiency

Planning for the demands of your application can help you determine how much capacity you need. However, application demand tends not to be constant over time. It may vary by day of the month or week or by hour of the day. It may even vary in response to expected or unexpected events. Ideally, we will constantly adjust our application's capacity based on the demand over time.

There are two ways to increase capacity: Scaling up and scaling out. Scaling up refers to using a more powerful virtual machine. Scaling out refers to deploying more instances of your application.


These categories are pillars, but they are not silos. Addressing one pillar can have implications in other pillars. For example, there are cost considerations for almost everything we do. And how we implement Operational Excellence may affect our Performance Efficiency. And monitoring is a key to almost all these pillars.

When designing an Azure application, it is important to consider each pillar and note that some tradeoffs may be necessary.

Next steps

For more information, visit the Azure Well-Architected Framework home page.

Microsoft Assessments contains an Azure Well-Architected Review that walks you through a series of questions to determine how well you have addressed some or all of the pillars.

In this article, we described the Microsoft Azure Well-Architected Framework and briefly covered each of the five pillars covered by this framework.

GCast 127:

Building and Running a Docker Container

Learn how to create a Docker image, push it to a repository; then build and manage a container based on that image.

DavidGray2022It is not often that a singer acts as his own warmup band. But that is exactly what David Gray did Monday night at the Huntington Bank Pavilion on Northerly Island.

Gray promised to play every track from his classic album "White Ladder" two decades after its release. But before he did so, he and his band performed a collection of his hits. The crowd was small, but they enjoyed hearing favourites, such as "The Other Side" and "You're the World to Me". After nearly an hour, the band left the stage, returning 20 minutes later to perform the album he promised.

True to his word, Gray sang each of the ten tracks in the order they appeared on the original CD. David has a talent for making his live performance sound very much like the studio version of his songs, which delighted the audience. The first two songs: "Please Forgive Me" and "Babylon" brought everyone to their feet. He concluded the set with the final track "Say Hello Wave Goodbye" - a mellower version of a song originally recorded by the synthpop band "Soft Cell".

Gray opened his encore set with another Soft Cell cover - their biggest hit "Tainted Love". The arrangement was close to the original - a style not often embraced.

David then told a story of the week that he performed at the prestigious Glastonbury Festival. It was the same week that "White Ladder" cracked the top 5 in the UK and he and his dad had a chance to meet David Bowie. Bowie was a big star and very gracious to the young upstarts, which prompted Mr. Gray to include two of Mr. Bowie's songs ("Life on Mars" and "Oh! You Pretty Things") in tonight's encore.

This was my first time seeing David Gray in concert. My friend Chris introduced me to his music earlier this year, telling me it was a favourite of him and his wife. I sat with them at the show and felt the emotion and joy that David Gray brings to his audience through his music.

NittyGrittyDirtBandBannerThe Nitty Gritty Dirt Band has been performing and performing well for a long time.

They formed over 50 years ago in Long Beach, CA. Although the musicians in the band have come and gone, singer/guitarist Jeff Hanna and drummer Jimmie Fadden have remained since the beginning and keyboardist/accordionist Bob Carpenter has been in the group for 45 years.

Saturday night at the City Winery, they were joined by Ross Holmes (mandolin and violin), Jim Photoglo (bass guitar), and Jeff Hanna (guitar). Jeff is the son of founding member Jeff Hanna and his father has reason to be proud of his talent. Individually, they were great, and together they were something special.

The Dirt Band has enjoyed success recording originals and cover songs over the years; and on this night, they mixed them well. Their latest album - "Dirt Does Dylan" - is a collection of covers by the great songwriter Bob Dylan and they played three selections from this record: "Girl from the North Country", "Forever Young", and "I Shall Be Released". But much of the evening, they focused on their earlier songs, from the upbeat "An American Dream" to Jerry Jeff Walker's "Mr. Bojangles" - arguably their biggest hit. They have also been a source of material for other artists. Dirt won a songwriting Grammy for "Bless the Broken Road" after it was recorded by Rascal Flatts. Hanna joked that the original recording was bought only by friends and family and failed to achieve Platinum status, settling for "aluminum" status instead.

Other highlights of the evening were "Long Hard Road" - a song written by Rodney Crowell about his sharecropper father; two Hank Williams songs: "Jambalaya" and "Honky Tonkin'"; and "The Working Man" - an original song inspired by their performance at the original Farm Aid in Champaign, IL. Fadden wrote and sang the latter song. He impressed me by playing drums and harmonica simultaneously - something I have never seen before.

This band tends to drop names of famous people with whom they collaborated; but they have every right to, given the impressive array of talent with whom they worked over the past five decades.

The encore bought the sold-out audience to its feet and had many of them dancing in the aisle. They closed with stirring renditions of the traditional "Will the Circle be Unbroken" and the Band's "The Weight".

It was a night to remember and left many smiles.

My Photos

<< Older Posts