Open Liberty with DerbyDB

13 March 2018

In this post I describe how to use Open Liberty with the lightweight Apache Derby database.

Here are the steps:

  1. Download Apache Derby.

  2. Configure the driver/datasource in the server.xml

        <!-- -->
        <variable name="DERBY_JDBC_DRIVER_PATH" value="/home/daniel/dev/tools/db-derby-"/>
        <library id="DerbyLib">
            <fileset dir="${DERBY_JDBC_DRIVER_PATH}"/>
        <dataSource id="DefaultDerbyDatasource" jndiName="jdbc/defaultDatasource" statementCacheSize="10" transactional="true">
           <jdbcDriver libraryRef="DerbyLib"/>
           <properties.derby.embedded connectionAttributes="upgrade=true" createDatabase="create" databaseName="/var/tmp/sample.embedded.db" shutdownDatabase="false"/>
    	   <!--properties.derby.client databaseName="/var/tmp/sample.db" user="derbyuser" password="derbyuser" createDatabase="create" serverName="localhost" portNumber="1527" traceLevel="1"/-->

    Note that the database is embeeded and file-based. This means, no database-server needs to be started manually. On application-server startup an embeeded database is started and will write to the file under databaseName. Use the memory: prefix, to just hold it in main-memory and not on the filesystem.

    As an alternative, you can also start the Derby-network-server seperately and connect by using the properties.derby.client instead.

  3. In case you want to use the datasource with JPA, provide a persistence.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.1" xmlns="" xmlns:xsi=""
    	<persistence-unit name="prod" transaction-type="JTA">
    			<property name="hibernate.show_sql" value="true" />
    			<property name="eclipselink.logging.level" value="FINE" />
    			<property name="javax.persistence.schema-generation.database.action" value="drop-and-create" />
    			<property name="javax.persistence.schema-generation.scripts.action" value="drop-and-create" />
    			<property name="javax.persistence.schema-generation.scripts.create-target" value="bootstrapCreate.ddl" />
    			<property name="javax.persistence.schema-generation.scripts.drop-target" value="bootstrapDrop.ddl" />

    With the default settings of Gradle’s war-plugin, you can place it under src/main/resources/META-INF and the build should package it under WEB-INF/classes/META-INF.

  4. You should now be able to inject the entity-manager via

    EntityManager em;

This blog has a similar guide on how to use PostgreSQL with Open Liberty.

Gradle and Arquillian for OpenLiberty

12 March 2018

In this post I describe how to use arquillian together with the container-adapter for Websphere-/Open-Liberty.

The dependencies are straight-forward as for any other container-adapter except the additional need for the tools.jar on the classpath:

dependencies {
    providedCompile 'javax:javaee-api:7.0'

    // this is the BOM
    testCompile 'org.jboss.arquillian:arquillian-bom:1.3.0.Final'
    testCompile 'org.jboss.arquillian.junit:arquillian-junit-container'

    testCompile files("${['java.home']}/../lib/tools.jar")
    testCompile 'org.jboss.arquillian.container:arquillian-wlp-managed-8.5:1.0.0.CR1'

    testCompile 'junit:junit:4.12'
    testCompile 'org.mockito:mockito-core:2.10.0'

A minimalistic arquillian.xml looks like the following:

<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns:xsi=""

        <property name="deploymentExportPath">build/deployments</property>

    <container qualifier="wlp-dropins-deployment" default="true">
            <property name="wlpHome">${wlp.home}</property>
            <property name="deployType">dropins</property>
            <property name="serverName">server1</property>


As there is no good documentation, on the supported properties, I had to look into the sources over on Github.

Also, you might not want to hard-code the wlp.home here. Instead you can define it in your build.gradle like this:

test {
    systemProperty "arquillian.launch", "wlp-dropins-deployment"
    systemProperty "wlp.home",['wlp.home']

This will allow you to run gradle -Pwlp.home=<path-to-wlp> test.

Gradle and Arquillian for Wildfly

28 February 2018

In this post I describe how to set up arquillian to test/deploy on Wildfly. Note that there is a managed and a remote-adapter. Managed will mean that arquillian manages the application-server and thus starts it. Remote means that the application-server was already started somehow and arquillian will only connect and deploy the application within this remote server. Below you will find the dependencies for both types of adpaters.

dependencies {
    providedCompile 'javax:javaee-api:7.0'

    // this is the BOM
    testCompile 'org.jboss.arquillian:arquillian-bom:1.3.0.Final'
    testCompile 'org.jboss.arquillian.junit:arquillian-junit-container'

    testCompile 'org.wildfly.arquillian:wildfly-arquillian-container-managed:2.1.0.Final'
    testCompile 'org.wildfly.arquillian:wildfly-arquillian-container-remote:2.1.0.Final'

    testCompile 'junit:junit:4.12'
    testCompile 'org.mockito:mockito-core:2.10.0'
Note that the BOM-import will only work with Gradle 4.6+

An arquillian.xml for both adapters looks like the following. The arquillian-wildfly-managed config is enabled here by default.

<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns:xsi=""

        <property name="deploymentExportPath">build/deployments</property>

    <!-- Start JBoss manually via:
        ./ -Djboss.socket.binding.port-offset=100 -server-config=standalone-full.xml
    <container qualifier="arquillian-wildfly-remote">
            <property name="managementPort">10090</property>

    <container qualifier="arquillian-wildfly-managed" default="true">
            <property name="jbossHome">/home/daniel/dev/app-servers/jboss-eap-7.0-test</property>
            <property name="serverConfig">${}</property>
            <property name="allowConnectingToRunningServer">true</property>

As an additional tip: I always set deploymentExportPath to a folder withing gradle’s build-directory because sometimes it is helpful to have a look at the deployment generated by arquillian/shrinkwrap.

In case you don’t want to define a default adapater or overwrite it (e.g. via a gradle-property from the commandline), you can define the arquillian.launch system property within the test-configuration.

test {
    systemProperty "arquillian.launch", "arquillian-wildfly-managed"

Gradle and Arquillian Chameleon

26 February 2018

The lastest Gradle 4.6 release candiates come with BOM-import support.

It can be enabled in the settings.gradle by defining enableFeaturePreview('IMPROVED_POM_SUPPORT').

With this, the Arquillian BOM can be easily imported and the dependecies to use Arquillian with the Chameleon Adapter look like the following:

dependencies {
    providedCompile 'javax:javaee-api:7.0'

	// this is the BOM
	testCompile 'org.jboss.arquillian:arquillian-bom:1.3.0.Final'
	testCompile 'org.jboss.arquillian.junit:arquillian-junit-container'
	testCompile 'org.arquillian.container:arquillian-container-chameleon:1.0.0.Beta3'

    testCompile 'junit:junit:4.12'
    testCompile 'org.mockito:mockito-core:2.10.0'

Chameleon allows to easily manage the container adapters by simple configuration in the arquillian.xml. As of today, Wildfly and Glassfish are supported but not Websphere liberty.

To define Wildfly 11, the following arquillian.xml (place under src/test/resources) is sufficient:

<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns:xsi=""

    <container qualifier="wildfly" default="true">
            <property name="chameleonTarget">wildfly:11.0.0.Final:managed</property>

With this little bit of Gradle and Arquillian magic, you should be able to run a test like below. The Wildfly 11 container will be downloaded on the fly.

public class GreetingServiceTest {

	public static WebArchive deployService() {
		return ShrinkWrap.create(WebArchive.class)

	private Service service;

	public void shouldGreetTheWorld() throws Exception {
		Assert.assertEquals("hello world", service.hello());

Gradle: Automatic and IDE-independent redeployments on OpenLiberty

25 February 2018

The last weeks I have started to experiment how well VSCode can be used for Java EE development. I have to say that it is quiet exciting to watch what the guys at Microsoft and Red Hat are doing with the Java integration. The gist of it: It cannot replace a real Java IDE yet for a majority of heavy development, but i can see the potential due to its lightweightness in projects that also involve a JavaScript frontend. The experience of developing Java and JavaScript in this editor is quiet nice compared to a beast like Eclipse.

One of my first goals for quick development: Reproduce the automatical redeploy you get from IDEs like Eclipse (via JBoss Tools). I.e. changing a Java-class automatically triggers a redeploy of the application. As long as you make sure the WAR-file is small, this deploy task takes less then a second and allows for quick iterations.

Here the steps how to make this work in VS Code; actually, they are independent of VSCode and just leverage Gradle’s continous-build feature.

Place this task in your build.gradle. It deploys your application to the dropins-folder of OpenLiberty if you have set up the environment variable wlpProfileHome.

task deployToWlp(type: Copy, dependsOn: 'war') {
    dependsOn 'build'
    from war.archivePath
    into "${System.env.wlpProfileHome}/dropins"

Additionally, make sure to enable automatic redeploys in your server.xml whenever the contents of the dropins-folder change.

<!-- hot-deploy for dropins -->
<applicationMonitor updateTrigger="polled" pollingRate="500ms" dropins="dropins" dropinsEnabled="true"/>

Every time you run gradlew deployToWlp, this should trigger a redeploy of the latest code.

Now comes the next step: Run gradlew deployToWlp -t for continuous builds. Every code-change should trigger a redeploy. This is indepdent of any IDE and thus works nicely together with VS Code in case you want this level of interactivity. If not, it is very easy to just map a shortcut to the gradle-command in VSCode to trigger it manually.

Arquillian UI Testing from Gradle

24 February 2018

Lets for this post assume we want to test some Web UI that is already running somehow. I.e. we don’t want to start up the container with the web-app from arquillian.

Arquillian heavily relies on BOMs to get the right dependencies. Gradle out of the box is not able to handle BOMs; but we can use the nebula-plugin. Import-scoped POMs are not supported at all.

So, make sure you have the following in your build.gradle:

plugins {
    id 'nebula.dependency-recommender' version '4.1.2'

apply plugin: 'java'

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {

dependencyRecommendations {
    mavenBom module: 'org.jboss.arquillian:arquillian-bom:1.2.0.Final'

dependencies {
    testCompile 'junit:junit:4.12'

    testCompile "org.jboss.arquillian.junit:arquillian-junit-container"
    testCompile "org.jboss.arquillian.graphene:graphene-webdriver:2.0.3.Final"

Now the test:

public class HackerNewsIT {

    WebDriver browser;

    public void name() {
        String title = browser.getTitle();
        Assert.assertThat(title,"Hacker News"));


Run with it with gradle test.

By default, HTMLUnit will be used as the browser. To use Chrome, download the

If you dont want to put it on your PATH, tie it to the WebDriver like this in your arquillian.xml:

 <arquillian xmlns="" xmlns:xsi=""

    <extension qualifier="webdriver">
        <property name="browser">chrome</property>
        <property name="chromeDriverBinary">/home/daniel/dev/tools/chromedriver</property>


Checkstyke with Gradle

30 January 2018

Get a checkstyle.xml and; e.g. from SUN and place in your gradle-project under config/checkstyle/checkstyle.xml.

Now add the following to your build.gradle:

apply plugin: 'checkstyle'

checkstyle {
    showViolations = true
    ignoreFailures = false

Run with it with gradle check.

If there are violations, a HTML-report will be written to build/reports/checkstyle.

OpenLiberty Java EE 8 Config

22 January 2018

When you create a new server in Websphere/Open Liberty via ${WLP_HOME}/bin/server create server1, the generated server.xml is not configured properly for SSL, Java EE, etc. Here is a minimal server.xml that works:

<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">

    <!-- Enable features -->

    <!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
    <httpEndpoint httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint"/>

    <keyStore id="defaultKeyStore" password="yourpassword"/>

    <!-- Automatically expand WAR files and EAR files -->
    <applicationManager autoExpand="true"/>

    	<user password="admin12!" name="admin"></user>

    <!-- hot-deploy for dropins -->
    <applicationMonitor updateTrigger="polled" pollingRate="500ms"
                    dropins="dropins" dropinsEnabled="true"/>

Together with this build.gradle file you can start developing Java EE 8 applications:

apply plugin: 'war'
apply plugin: 'maven'

group = 'de.dplatz'
version = '1.0-SNAPSHOT'

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {

dependencies {
    providedCompile 'javax:javaee-api:8.0'
    testCompile 'junit:junit:4.12'

war {
    archiveName 'webapp.war'

task deployToWlp(type: Copy, dependsOn: 'war') {
    dependsOn 'build'
    from war.archivePath
    into "${System.env.wlpProfileHome}/dropins"

OpenLiberty Debug Config

21 January 2018

You can run a Websphere/Open Liberty via ${WLP_HOME}/bin/server debug server1 in debug-mode. But this makes the server wait for a debugger to attach. How to attach later?

Create a file ${WLP_HOME}/usr/servers/server1/jvm.options and add the debug-configuration:


Now you can use ${WLP_HOME}/bin/server run server1.

Gradle deploy-task

20 January 2018

Deploy to e.g. Websphere liberty by adding this task to your build.gradle file:

task deployToWlp(type: Copy, dependsOn: 'war') {
    dependsOn 'build'
    from war.archivePath
    into "${System.env.wlpProfileHome}/dropins"

Assuming you have the environment-variable set, you can now run gradlew deployToWlp.

Implementing JAX-RS-security via Basic-auth

31 October 2017

Basic-auth is the simplest and weakest protection you can add to your resources in a Java EE application. This post shows how to leverage it for JAX-RS-resources that are accessed by a plain HTML5/JavaScript app.

Additionally, I had the following requirements:

  • The JAX-RS-resource is requested from a prue JavaScript-based webapp via the fetch-API; I want to leverage the authentication-dialog from the browser within the webapp (no custom dialog as the webapp should stay as simple as possible and use as much as possible the standard offered by the browser).

  • But I don’t want the whole WAR (i.e. JavaScript app) to be protected. Just the request to the JAX-RS-endpoint should be protected via Basic-auth

  • At the server-side I want to be able to connect to my own/custom identity-store; i.e. I want to programatically check the username/password myself. In other words: I don’t want the application-server’s internal identity-stores/authentication.

Protecting the JAX-RS-endpoint at server-side is as simple as implementing a request-filter. I could have used a low-level servlet-filter, but instead decided to use the JAX-RS-specific equivalent:


public class SecurityFilter implements ContainerRequestFilter {

	public void filter(ContainerRequestContext requestContext) throws IOException {
		String authHeader = requestContext.getHeaderString("Authorization");
		if (authHeader == null || !authHeader.startsWith("Basic")) {
			requestContext.abortWith(Response.status(401).header("WWW-Authenticate", "Basic").build());

		String[] tokens = (new String(Base64.getDecoder().decode(authHeader.split(" ")[1]), "UTF-8")).split(":");
		final String username = tokens[0];
		final String password = tokens[1];

		if (username.equals("daniel") && password.equals("123")) {
			// all good
		else {


If the Authorization header is not present, we request the authentication-dialog from the browser by sending the header WWW-Authenticate=Basic. If i directly open up the JAX-RS-resource in the browser, I get the uthentication-dialog from the browser and can access the resource (if I provide the correct username and password).

Now the question is if this also works when the JAX-RS-resource if fetched via the JavaScript fetch-API. I tried this:

function handleResponse(response) {
	if (response.status == "401") {
		alert("not authorized!")
	} else {
		response.json().then(function(data) {


It did not work; I was getting 401 from the server because the browser was not sending the "Authorization" header; but the browser also did not show the authentication-dialog.

A peak into the spec hinted that it should work:

  1. If request’s use-URL-credentials flag is unset or authentication-fetch flag is set, then run these subsubsteps: …​

  2. Let username and password be the result of prompting the end user for a username and password, respectively, in request’s window.

So, i added the credentials to the fetch:

fetch("http://localhost:8080/service/resources/health", {credentials: 'same-origin'}).then(handleResponse);

It worked. The browser shows the authentication-dialog after the first 401. In subsequent request to the JAX-RS-resouce, the "Authorization" header is always sent along. No need to reenter every time (Chrome discards it as soon as the browser window is closed).

The only disadvantage I found so far is from a development-perspective. I usually run the JAX-RS-endpoint seperately from my Javascript app; i.e. the JAX-RS-endpoint is hosted as a WAR in the application-server but the JavaScript-app is hosted via LiveReload or browser-sync. In this case, the JAX-RS-service and the webapp do not have the same origin (different port) and I have to use the CORS-header Access-Control-Allow-Origin=* to allow communication between the two. But with this header set, the Authorization-token collected by the JavaScript-app will not be shared with the JAX-RS-endpoint.

Github - Switch to fork

05 October 2017

Say you just have cloned a massive github repository (like Netbeans) where cloning already takes minutes and now decide to contribute. You will fork the repo and than clone the fork and spend another X minutes waiting?

This sometimes seems like to much of an effort. And thankfully, there are steps how you can transform the already cloned repo to use your fork.

  1. Fork the repo

  2. Rename origin to upstream (your fork will be origin)

    git remote rename origin upstream
  3. Set origin as your fork

    git remote add origin
  4. Fetch origin

    git fetch origin
  5. Make master track new origin/master

    git checkout -B master --track origin/master

Websphere Administration via JMX, JConsole and JVisualVM

25 September 2017

How to connect to the Websphere-specific MBean server to configure the environment and monitor the applications?

Start JConsole with the following script:


# Change me!
export HOST=swpsws16
export IIOP_PORT=9811

export WAS_HOME=/home/daniel/IBM/WebSphere/AppServer

export PROVIDER=-Djava.naming.provider.url=corbaname:iiop:$HOST:$IIOP_PORT

export CLASSPATH=$CLASSPATH:$WAS_HOME/java/lib/tools.jar
export CLASSPATH=$CLASSPATH:$WAS_HOME/java/lib/jconsole.jar

export URL=service:jmx:iiop://$HOST:$IIOP_PORT/jndi/JMXConnector

$WAS_HOME/java/bin/java -classpath $CLASSPATH $PROVIDER $URL

Even nicer: Install VisualWAS plugin for JVisualVM.

  • Use "Add JMX Connection"

  • Use Connection-Type "Websphere"

  • For port, use SOAP_CONNECTOR_ADDRESS (default 8880)

Websphere and JVisualVM

25 September 2017

How to inspect a Websphere server via JVisualVM?

Go to "Application servers > SERVER-NAME > Java and Process management > Process Defintion > Java Virtual Machine > Generic JVM arguments" and add the following JMV settings: \ \ \ \ \ \

Providing an external ip or hostname was important for it to work.

Select "Add JMX Connection" in JVisualVM and enter:

Jenkins in Docker using Docker

23 September 2017

Say you want to run your Jenkins itself in docker. But the Jenkins build-jobs also uses docker!?

Either you have to install docker in docker, or you let the Jenkins docker-client access the host’s docker-daemon.

  1. Map the unix socket into the Jenkins container:

    -v /var/run/docker.sock:/var/run/docker.sock
  2. But the jenkins user will not have permissions to access the socket by default. So, first check the GID of the group that owns the socket:

    getent group dockerroot
  3. Now create a group (name is irrelevant; lets name it "docker") in the Jenkins container with the same GID and assign the jenkins user to it:

    sudo groupadd -g 982 docker
    sudo usermod -aG docker jenkins

ES6 with Nashorn in JDK9

14 June 2017

JDK9 is planning to incrementally support the ES6 features of JavaScript. In the current early-access builds (tested with 9-ea+170), major features like classes are not supported yet; but keywords like let/const, arrow functions and string-interpolation already work:

#!jjs --language=es6
"use strict";

let hello = (from, to) => print(`Hello from ${from} to ${to}`);

if ($EXEC('uname -n')) {
    let hostname = $OUT.trim();
    hello(hostname, 'daniel');

For details on what’s included by now, read JEP 292.

AWS ECS: Push a docker container

28 May 2017

Steps to deploy docker containers to AWS EC2:

  1. Created a docker-repository with the name de.dplatz/abc, you will get a page with all the steps and coordinates for docker login, docker tag and docker push.

  2. From CLI run:

    aws ecr get-login --region eu-central-1
    docker tag de.dplatz/abc:latest <my-aws-url>/de.dplatz/abc:latest
    docker push <my-aws-url>/de.dplatz/abc:latest

See here for starting the container.

JDK9 HttpClient

20 May 2017

Required some clarification from the JDK team how to access the new HttpClient API (which actually is incubating now):

$ ./jdk-9_168/bin/jshell --add-modules jdk.incubator.httpclient
|  Welcome to JShell -- Version 9-ea
|  For an introduction type: /help intro

jshell> import jdk.incubator.http.*;

jshell> import static jdk.incubator.http.HttpResponse.BodyHandler.*;

jshell> URI uri = new URI("");
uri ==>

jshell> HttpRequest request = HttpRequest.newBuilder(uri).build();
request ==> GET

jshell> HttpResponse response = HttpClient.newBuilder().build().send(request, discard(null));
response ==> jdk.incubator.http.HttpResponseImpl@133814f

jshell> response.statusCode();
$6 ==> 200

I really like the jshell-integration in Netbeans; unfortunately, it does not allow to set commandline-flags for the started shells yet. Filed an issue and got a workaround for now.

Websphere Liberty Admin Console

12 May 2017

$ bin/installUtility install adminCenter-1.0
<!-- Enable features -->
    <!-- ... -->

<keyStore id="defaultKeyStore" password="admin123" />

<basicRegistry id="basic" realm="BasicRealm">
    <user name="admin" password="admin123" />
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://localhost:9090/adminCenter/

Docker JVM Memory Settings

01 May 2017

Read this, this and this.

  • JDK9 has -XX:+UseCGroupMemoryLimitForHeap

  • JDK8 pre 131: Always specify -Xmx1024m and -XX:MaxMetaspaceSize

  • JDK8 since 131: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap

Docker Rest API

01 May 2017

SSL keys are at /cygdrive/c/Users/<username>/.docker/machine/machines/default

 curl --insecure -v --cert cert.pem --key key.pem -X GET


01 May 2017

strace -fopen,read,close,fstat java -jar Test.jar

Stacktrace in Eclipse Debugger

12 April 2017

How to see the stacktrace for an exception-variable within the eclipse debugger?

Go to Preferences / Java / Debug / Detail Formatter; Add for Throwable: stackTrace = new; printWriter = new;
return getMessage() + "\n" + stackTrace;

Java debug-flags

22 March 2017

// shared-memory (windows only)
// socket


07 March 2017

Monitor filesystem-changes:

while inotifywait -qr /dir/to/monitor; do
    rsync -avz /dir/to/monitor/ /dir/to/sync/to

List classes in Jar

29 January 2017

List all classes in a jar-file:

$ unzip -l MyJar.jar "*.class" | tail -n+4 | head -n-2 | tr -s ' ' | cut -d ' ' -f5 | tr / . | sed 's/\.class$//'

rsync tricks

20 January 2017

This command removes files that have been removed from the source directory but will not overwrite newer files in the destination:

$ rsync -avu --delete sourcedir/ /cygwin/e/destdir/

To rsync to another system with ssh over the net:

$ rsync -avu --delete -e ssh sourcedir/ username@machine:~/destdir/

Shell Alias-Expansion

17 January 2017

Say, you have defined an alias:

$ alias gg='git log --oneline --decorate --graph'

But when typing 'gg' wouldn’t it be nice to expand the alias so you can make a small modification to the args?

$ gg<Ctrl+Alt+e>

Say, you want to easily clear the screen; there is a shortcut Ctrl+L. But maybe you also always want to print the contents of the current directory: you can rebind the shortcut:

$ bind -x '"\C-l": clear; ls -l'

Java Version Strings

16 January 2017

For what JDK version is a class compiled?

$ javap -verbose MyClass.class | grep "major"
  • Java 5: major version 49

  • Java 6: major version 50

  • Java 7: major version 51

  • Java 8: major version 52

SSH Keys

13 January 2017

To connect to a remote-host without password-entry (for scripting):

# generate ssh keys for local (if not already done)
$ ssh-keygen
$ ssh-copy-id -i ~/.ssh/ <remote-host>
$ ssh <remote-host>

Maven Fat & Thin Jar

12 January 2017

Building a fat and a thin jar in one go:

                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">

Commandline HTTP-Server

10 January 2017

A very simple http-server:

while true ; do echo -e  "HTTP/1.1 200 OK\nAccess-Control-Allow-Origin: *\n\n $(cat index.html)" |  nc -l localhost 1500; done

Older posts are available in the archive.