Thursday, April 6, 2017

How to Shade a JAR and Relocate Classes in Maven

The example below shows how to shade org.fredy.myjar and guava JARS and rename the Guava classes that contain com.google.guava to org.fredy.com.google.guava.
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.fredy</groupId>
  <artifactId>shaded</artifactId>
  <version>0.0.1</version>
  <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.fredy</groupId>
      <artifactId>myjar</artifactId>
      <version>0.0.1</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.0.0</version>
        <configuration>
          <relocations>
            <relocation>
              <pattern>com.google.common</pattern>
              <shadedPattern>org.fredy.com.google.common</shadedPattern>
            </relocation>
          </relocations>
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <filters>
                <filter>
                  <artifact>*:*</artifact>
                  <excludes>
                    <exclude>META-INF/*.SF</exclude>
                    <exclude>META-INF/*.DSA</exclude>
                    <exclude>META-INF/*.RSA</exclude>
                  </excludes>1
                </filter>
              </filters>
              <promoteTransitiveDependencies>true</promoteTransitiveDependencies>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Friday, March 3, 2017

How to Cancel a Goroutine in Go

The example below shows how to cancel a goroutine while is in the middle of executing a long-running task.
package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    busyChan := make(chan bool)

    ctx, cancel := context.WithCancel(context.Background())
    go func(ctx context.Context) {
        for {
            select {
            case <-busyChan:
                fmt.Println("Pretending to be very busy")
                time.Sleep(5000 * time.Second)
            case <-ctx.Done():
                return
            }
        }
    }(ctx)
    busyChan <- true
    fmt.Println("Doing some other things")
    time.Sleep(3 * time.Second)
    fmt.Println("Stopping the goroutine")
    cancel()
}
Output:
Prentending to be very busy
Doing some other things
Stopping the goroutine

Wednesday, February 22, 2017

How to Embed JavaScript in Java

Java 8 came with a JavaScript engine called Nashorn. This makes it easy to call some JavaScript code from Java. In this example, I'm going to show how to pass some Java object into JavaScript and vice-versa as well as calling creating a Java object from JavaScript.
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.SimpleBindings;
import java.util.Map;

public class JsExample {
    public static class JavaClass {
        public String greet() {
            return "Hello from Java";
        }
    }

    public static void main(String[] args) throws Exception {
        final String script =
            "var File = Java.type(\"java.io.File\");" +
            "print(new File(\".\").exists());" +
            "var map = {\"msg\": \"Hello from JS\"};" +
            "print(javaClass.greet());" +
            "map;";

        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");

        Bindings bindings = new SimpleBindings();
        bindings.put("javaClass", new JavaClass());

        Map<String, String> retVal = (Map<String, String>) engine.eval(script, bindings);
        System.out.println(retVal.get("msg"));
    }
}
Output:
true
Hello from Java
Hello from JS