Docker Swarm

Initialize the swarm

docker swarm init --listen-addr 195.122.17.92:3000 --advertise-addr 10.10.0.6

We need the –advertise-addr because there are two IP addresses assigned to the same interface.

Create a service

docker service create --name my-service --publish 3000:3000 my-image:1.0.0

Set the service to be hosted on two nodes

docker service update --replicas 2 my-service

Typescript Web Browser Modules

I started with a question: how can I write Typescript modules to run in a Web browser without using Webpack or some other bundler?

I’ve used TypeScript for programming in Nodejs, and for writing user interfaces. These interface run in Web browsers and on mobile devices (mostly using React and React Native). When targeting the Web, I can start from a template like create-react-app. But, that uses Webpack under the hood. Also, using a UI component library is outside the scope of this project.

I can compile the TypeScript to JavaScript and import that into my Web document using a script tag. But then all the code that I want to include on the page needs to be written in one file. I don’t want to do that, so what else can I do?

The Setup

This is how my project is structured.

src/
  main.ts
  Class1.ts
  Class2.ts
  types.ts
static/
  js/
  index.html
  style.css
tsconfig.json

Notice there is currently no JavaScript files in the js directory. This is where I want to transpiled the Typescript to go. The main.ts will be the main method for programming the index.html. I’ll use all the classes and the types file in the main file.

TypeScript Config

Here’s the tsconfig.json file I’m using to accomplish my goal.

{
  "compilerOptions": {
    "target": "es2016",
    "module": "AMD",
    "rootDir": "./src",
    "outFile": "./static/js/script.js",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

For the most part, this is the default configuration. I’ve added entries for module, rootDir, and outFile. The key here is compiling the sources under the rootDir, to an AMD module in the outFile.

AMD Loader

Since we’ll be using AMD modules, we’ll need an AMD module loader in our Web document. I got that from the Dojo CDN by adding the following script tag to my index.html file.

<script src="https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>

Conclusion

Now, all the elements are in place:

  • A Web document (static/index.html)
  • An AMD loader in our Web document
  • Typescript source code (src/)
  • A tsconfig.json for transpiling our source into JavaScript AMD modules

The last thing we need to do is have typescript perform the transpiling and include our main.js file in our Web document.

This approach shows how we can write Typescript modules to run in a Web browser without using Webpack or some other bundler.

.NET Core REST API Notes

In the realm of enterprise software, two programming languages have dominated: C# (c sharp) and Java. Java has a runtime environment – which must be installed on computers that want to run Java code – called the JVM, and likewise C# has a runtime environment called .NET. I have a lot of experience with Java/JVM, but not as much with C#/.NET. Of the two languages, Java is probably more popular. This is likely (at least in part) due to the fact that Java and the JVM were open source while C#/.NET’s source code had been Microsoft’s property and closed to the public.

Since June 2016, a version of .NET has been available as open source software. That version is .NET Core (.NET Framework is the closed source relative). After learning about the open source release, I wanted to work with the C#/.NET system. Here, I’m going to document my notes on building a simple REST API connected to an SQL database – in this case, PostgreSQL (which is case sensitive, and that matters).

Installation

Installation of .NET Core is pretty easy. Here’s a link to Microsoft’s website with details for different operation systems:

https://docs.microsoft.com/en-us/dotnet/core/install

Starting the Project

To start a new .NET Core REST API, we can issue a single command. After the command runs, we’ll have a C#/.NET project scaffold in our project directory.

dotnet new webapi -o [project-name]
ls [project-name]
appsettings.Development.json
bin
[project-name].csproj
Program.cs
Startup.cs
appsettings.json
Controllers
obj
Properties
WeatherForecast.cs

To start the application, we can issue this command:

dotnet run
warn: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to bind to https://localhost:5001 on the IPv6 loopback interface: 'Cannot assign requested address'.
warn: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to bind to http://localhost:5000 on the IPv6 loopback interface: 'Cannot assign requested address'.
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: /app

HTTPS/HTTP and CORS

By default the application is configured for HTTPS. I’ll be hosting my project from a container service which will provide the HTTPS. So to make things easier, I’ll turn off HTTPS. To do this first specify the listen addresses (with port number), then tell the program not to redirect to HTTPS in Startup.cs.

Specify Listen Addresses

appsettings.json

In the appsettings.json, we can add a section for configuring the Kestrel server.

{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://0.0.0.0:3000"
      },

      {
        "Https": {
          "Url": "https://0.0.0.0:3001"
        },
      }
    }
  },
}

Program.cs

In Program.cs, call the UseUrls method on the WebBuilder object to specify the server’s listen addresses.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseUrls("http://+:5000");
                webBuilder.UseStartup<Startup>();
            });
}

In Startup.cs, simply comment out or remove the line in the Configure method with the call to app.UseHttpsRedirection.

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "lists_api v1"));
    }

    // app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Add CORS Policy

Add the following policy to the ConfigureService method in the Startup.cs class.

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "VtagApi", Version = "v1" });
            });

            services.AddCors(o => o.AddPolicy("AllowAll", builder =>
            {
                builder.AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader();
            }));
        }

Apply CORS Policy

Call app.UseCors method to use AllowAll policy.

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "VtagApi v1"));
            }
            // app.UseHttpsRedirection();

            app.UseCors("AllowAll");

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

HTTP Requests and Responses

Entity Framework Core

Entity Framework Core is an Object Relational Mapping (ORM) tool that maps database entities to C# objects.

Migrations

The following dotnet cli commands can be used to perform migrations.

First, make desired changes to the Models or database context. Then, create the migration.

dotnet ef migrations add <MIGRATION_NAME>

This will add a migration script to the Migrations directory. To execute the migration:

dotnet ef database update

Revert Migrations

First, list the database migrations.

dotnet ef migration list

From that list grab the name of the migration you want to revert to.

dotnet ef database update <MIGRATION_NAME>

Then, remove add the reverted migrations.

dotnet ef migrations remove

Case Sensitive Table Column Names

Install MongoDB Driver

dotnet add [ProjectName].csproj package MongoDB.Driver

Column/Property Value Converters

Often times, our C# and database data types don’t quite match up. Using a string for a VARCHAR, works “out of the box” with the EF, but matching enumerated types from the database is a bit trickier. We’ll also look at converting a TEXT type from the database into a C# List<string>. With this conversion in place we can store and work with CSV strings.

Namespaces

This section contains information about important Namespaces using in the creation of the REST API application.

Annotations

System.ComponentModel.DataAnnotations.Schema

  • Table – directs a Model class to use specified database table.
namespace MyApi
{
    [Table("entities")]
    public class Entity
    {
        // Model class defined here.
    }
}
  • Column – specify which column the Model property is mapped to.
namespace MyApi
{
    [Table("entities")]
    public class Entity
    {
        [Column("size")]
        public int Size { get; set; }

        // Model class defined here.
    }
}
  • NotMapped – tell Entity Framework not to map a property/column.
namespace MyApi
{
    [Table("entities")]
    public class Entity
    {
        [NotMapped]
        public int Name { get; set; }

        // Model class defined here.
    }
}

Docker

Using Docker with .NET Core apps is pretty simple.

Run Maven Project from CLI

This is just a quick not on how to run a maven project from the CLI – command line interface.

  1. cd into the root directory of the project.
  2. Run mvn compile.
  3. Then, to execute a class with a main method (usually the Application class) execute the following Maven command:
mvn exec:java -Dexec.mainClass=[your class here]

For example, let’s say you have a class with a main method in called Application, and that class is in a package named com.myname.myproject. Then the command to execute the main method would be:

mvn exec:java -Dexec.mainClass=com.myname.myproject.Application
Ubuntu Logo

Ubuntu System Services

This post about systemd has been published from a draft, so it’s not been proofed for publication. I find it useful, so I would like it readily available on-line. If you find anything wrong with it, please

Ubuntu, like many GNU/Linux distributions, uses systemd. systemd is a system used by the OS tor manage process, known as services. We can add our own services to systemd, and I’ll show how to do that in this post.

Services are useful, for example, if you start and run server. If we start that server as a user, the process running the server will be killed when the user logs out. If we want the server to run continuously – which is usually the case with servers – this is a problem.

We can be keep the service running by abandoning the process before logout, but it’s a hassle. In this set up, we would need to login, start the server, then abandoning processes. Instead, we can use systemd services and have the server started automatically (or on demand) and it runs in the background.

Systemd Unit Files

Our unit files go in the Systemd system directory.

/etc/systemd/system

Each service should have a name of the following form:

[name].service

Here’s an example of the format of the file.

[Unit]
Description=My Node.js Service

[Service]
WorkingDirectory=/home/jason/my-app
Restart=on-failure
ExecStart=/home/jason/my-app/dist/index.js

# Note: Debian/Ubuntu uses 'nogroup', RHEL/Fedora uses 'nobody'.
# Note: when 'ExecStart' is used, 'Type' defaults to 'simple'.

Environment=PATH=/usr/bin:/usr/local/bin
Environment=NODE_ENV='production'
Environment=ORACLE_HOME=/usr/lib/oracle/18.3/client64
Environment=LD_LIBRARY_PATH=/usr/lib/oracle/18.3/client64/lib

[Install]
WantedBy=multi-user.target

For more information on Service files, see the man page.

man systemd.service

Update Systemd Services

 sudo systemctl daemon-reload 
 
sudo systemctl enable my-webapp.service

Created symlink /etc/systemd/system/multi-user.target.wants/event-tracker-api.service → /etc/systemd/system/event-tracker-api.service.

 
sudo systemctl start my-webapp
sudo systemctl stop my-app
sudo systemctl status my-webapp

Command:

sudo service [name] {start,stop,restart,status}
Maven Logo

Maven: Setting Compiler Version

I recently started a new JavaFX project. I decided to use Maven because the tool is great for building Java projects in a standard way that conforms with best practices. Unfortunately, I’m not the most well versed in the tool. I’ve used it a few times, and “it just worked”.

This evening I got the following errors when attempting to compile my project:

Source option 5 is no longer supported. Use 7 or later.
Target option 5 is no longer supported. Use 7 or later.

I didn’t know what it meant, so I went to the Web. A search result later, I learned this had to do with the compiler. So I added the following directive to my pom.xml file.

    <properties>
        <maven.compiler.source>13</maven.compiler.source>
        <maven.compiler.target>13</maven.compiler.target>
    </properties>

I’m using openjdk-13, so I told Maven that my source code (compiler.source) would be written in Java 13; and that my output code (compiler.target) should run on the Java 13 JVM.

If we were to compile directly on the command line, we could use -source and -target flags reach the same end, but I believe Maven leverages a javax.tools.JavaCompiler object that enables invocation of the Java compiler from within programs. From what I can tell, it’s the Maven Compiler Plugin which uses such an object – hence, the maven.compiler.* directives.