I am currently using cucumber and the masterthought plugin to generate html reports on test executions. I want to enable future flexibility to configure the cucumber options when running my tests from a gradle script as well as running the cucumber from java code without the need of using plugins on build script.
I have previously used the surefire plugin to run the cucumber and the masterthought plugin to generate the cucumber report
package com.my.domain;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.junit.runner.RunWith;
import org.junit.runners.model.InitializationError;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import cucumber.runtime.RuntimeOptions;
import cucumber.runtime.RuntimeOptionsFactory;
import net.masterthought.cucumber.Configuration;
import net.masterthought.cucumber.ReportBuilder;
import net.masterthought.cucumber.Reportable;
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {
"json:build/path/cucumber.json" },
features = {
"src/main/resources/features" },
glue = {
"com.my.domain.stepdefinitions" },
dryRun = false,
tags = {"#tag"}
)
public class CucumberJunitRunner {
// TODO: Make Tags, Features, Glue, plugin runtime, and path configurable
private static final String JSON_PLUGIN_PREFIX = "json:";
private static final String PRECONFIGURED_REPORT_OUTPUT_FOLDER_NAME = "cucumber-html-reports";
private static final Optional<String> REPORT_OUTPUT_FOLDER_LOCATION = Optional.ofNullable(null);
private static final boolean SKIP_REPORT_GENERATION = false;
public static void main(String[] args) throws InitializationError {
RuntimeOptions cucumberRuntimeOptions = null;
Optional<String> jsonPluginOutputLocation = Optional.empty();
if(args.length > 0) {
//TODO: USE ARGUMENTS TO INITIALIZE cucumberRuntimeOptions AND jsonPluginOutputLocation
} else {
RuntimeOptionsFactory cucumberRuntimeOptionsFactory = new RuntimeOptionsFactory(CucumberJunitRunner.class);
cucumberRuntimeOptions = cucumberRuntimeOptionsFactory.create();
jsonPluginOutputLocation = cucumberRuntimeOptions.getPluginFormatterNames().stream()
.filter(s -> s.startsWith(JSON_PLUGIN_PREFIX))
.map(s -> s.substring(JSON_PLUGIN_PREFIX.length())).findFirst();
if( ! jsonPluginOutputLocation.isPresent() ) {
throw new RuntimeException(String.format(
"Could not find jsonPluginOutputLocation in plugins from cucumber options: %s",
cucumberRuntimeOptions.getPluginFormatterNames()));
}
}
deletePreviousData(jsonPluginOutputLocation);
runCucumber(cucumberRuntimeOptions, Thread.currentThread().getContextClassLoader());
if (SKIP_REPORT_GENERATION) {
System.out.println("Report generation skipped. No HTML report was built.");
} else {
if (cucumberRuntimeOptions.isDryRun()) {
System.out.println("Cucumber DryRun executed. No HTML report was built.");
} else {
if (jsonPluginOutputLocation.isPresent()) {
Path jsonPluginOutputPath = Paths.get(jsonPluginOutputLocation.get());
if (Files.exists(jsonPluginOutputPath)) {
generateCucumberReport(
REPORT_OUTPUT_FOLDER_LOCATION.orElse(
FilenameUtils.getFullPathNoEndSeparator(jsonPluginOutputLocation.get())),
jsonPluginOutputLocation.get(), "1", "My Project");
} else {
System.out.println("Cucumber JSON report was missing. No HTML report was built.");
}
} else {
System.out.println("Cucumber JSON plugin was missing. No HTML report was built.");
}
}
}
}
private static void deletePreviousData(Optional<String> jsonPluginOutputLocation) {
Path jsonPluginOutputPath = Paths.get(jsonPluginOutputLocation.get());
if (Files.exists(jsonPluginOutputPath)) {
try {
Files.delete(jsonPluginOutputPath);
System.out.println("Cucumber JSON file was deleted: " +
jsonPluginOutputPath.toAbsolutePath().toString());
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("Cucumber JSON file from previous execution was not detected: "
+ jsonPluginOutputPath.toAbsolutePath().toString());
}
Path cucumberReportsFolder = jsonPluginOutputPath.resolveSibling(PRECONFIGURED_REPORT_OUTPUT_FOLDER_NAME);
if (Files.exists(cucumberReportsFolder)) {
try {
FileUtils.deleteDirectory(cucumberReportsFolder.toFile());
System.out.println("Cucumber JSON report was deleted: " +
cucumberReportsFolder.toAbsolutePath().toString());
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("Cucumber JSON report from previous execution was not detected: "
+ cucumberReportsFolder.toAbsolutePath().toString());
}
}
/**
* Launches the Cucumber-JVM command line.
*
* #param argv runtime options. See details in the
* {#code cucumber.api.cli.Usage.txt} resource.
* #param classLoader classloader used to load the runtime
* #return 0 if execution was successful, 1 if it was not (test failures)
*/
public static byte runCucumber(RuntimeOptions cucumberRuntimeOptions, ClassLoader classLoader) {
final cucumber.runtime.Runtime runtime = cucumber.runtime.Runtime.builder()
.withRuntimeOptions(cucumberRuntimeOptions).withClassLoader(classLoader).build();
runtime.run();
return runtime.exitStatus();
}
private static void generateCucumberReport(String reportOutputDirectoryLocation, String cucumberJsonFile,
String buildNumber, String projectName) {
File reportOutputDirectory = new File(reportOutputDirectoryLocation);
List<String> jsonFiles = new ArrayList<>();
jsonFiles.add(cucumberJsonFile);
// jsonFiles.add("cucumber-report-2.json");
// String buildNumber = "1";
// String projectName = "cucumberProject";
boolean runWithJenkins = false;
Configuration configuration = new Configuration(reportOutputDirectory, projectName);
// optional configuration - check javadoc
configuration.setRunWithJenkins(runWithJenkins);
configuration.setBuildNumber(buildNumber);
// addidtional metadata presented on main page
// configuration.addClassifications("Platform", "Windows");
// configuration.addClassifications("Browser", "Firefox");
// configuration.addClassifications("Branch", "release/1.0");
// optionally add metadata presented on main page via properties file
//List<String> classificationFiles = new ArrayList<>();
//classificationFiles.add("properties-1.properties");
//classificationFiles.add("properties-2.properties");
// configuration.addClassificationFiles(classificationFiles);
ReportBuilder reportBuilder = new ReportBuilder(jsonFiles, configuration);
Reportable result = reportBuilder.generateReports();
// and here validate 'result' to decide what to do if report has failed
if (result == null) {
System.out.println("There was an isssue while building the report");
System.exit(1);
}
System.out.println(result);
}
}
Related
I need to find all PDAnnotationLink in a document and replace their default actions with PDActionJavaScript ones.
The final goal is to make the link open in a new tab but for now I just want alert to be displayed on click.
Here is the test example:
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.interactive.action.PDAction;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionURI;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink;
import org.junit.Test;
/**
*
*/
public class PdfBoxTest {
#Test
public void testReplaceLinks() throws Exception {
String pathPrefix = ...path to pdf file with links...;
Path originalPdf = Paths.get(pathPrefix + "links_test.pdf");
PDDocument doc = PDDocument.load(originalPdf.toFile());
doc.getDocumentCatalog().getPages().forEach(page -> {
try {
page.getAnnotations().forEach(pdAnnotation -> {
if (pdAnnotation instanceof PDAnnotationLink) {
PDAnnotationLink link = (PDAnnotationLink) pdAnnotation;
PDAction action = link.getAction();
if (action instanceof PDActionURI) {
PDActionURI uri = (PDActionURI) action;
PDActionJavaScript javaScript =
new PDActionJavaScript("app.alert(\"" + uri.getURI() + "\");");
// actual goal of replacing the links is to open them in a new tab/window
// PDActionJavaScript javaScript =
// new PDActionJavaScript("app.launchURL(\"" + uri.getURI() + "\", true);");
link.setAction(javaScript);
}
}
});
} catch (Throwable t) {
throw new RuntimeException(t);
}
});
Path modifiedPdf = Paths.get(pathPrefix + "links_test_mod.pdf");
doc.save(modifiedPdf.toFile());
}
}
but the document just renders the link label which is not clickable (no alert is shown).
I'm sure I'm missing something here.
Here are the links to the PDF files.
Original:
https://www.dropbox.com/s/notwf6yde5okh7g/links_test_orig.pdf?dl=0
Modified:
https://www.dropbox.com/s/bejj6rawwjrbyyc/links_test_mod.pdf?dl=0
Suppose that I have a maven project located in /home/admin/projects/maven-sample-project, I can package the project to a jar using the following command.
mvn clean package
Now I want to do it with Java and relevant maven-api, is there something like this?
MavenProject mavenProject = new MavenProject("/home/admin/projects/maven-sample-project");
mavenProject.clean();
mavenProject.package(jarLocation = "/home/admin/projects/maven-sample-project/target/maven-sample-project-1.0.0-SNAPSHOT.jar");
As mentioned by khmarbaise, maven-invoker is able to solve this problem.
First add the dependency in your pom.xml file.
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-invoker</artifactId>
<version>3.0.1</version>
</dependency>
Then create a new class.
import org.apache.maven.shared.invoker.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MavenRunner {
public static final String MAVEN_COMMAND_CLEAN = "clean";
public static final String MAVEN_COMMAND_PACKAGE = "package";
public static void run(String mavenProjectLocation, List<String> goals) throws MavenInvocationException {
Invoker invoker = getInvoker(mavenProjectLocation);
InvocationRequest request = getInvocationRequest(mavenProjectLocation, goals);
InvocationResult result = invoker.execute(request);
if ( result.getExitCode() != 0 )
{
String exceptionMsgPrefix = String.format("Failed to run maven commands, mavenProjectLocation: %s, goals: %s.", mavenProjectLocation, goals);
if ( result.getExecutionException() != null )
{
throw new MavenInvocationException(exceptionMsgPrefix + "exception: " + result.getExecutionException());
}
else
{
throw new MavenInvocationException(exceptionMsgPrefix + "exit code: " + result.getExitCode());
}
}
}
private static Invoker getInvoker(String mavenProjectLocation) {
Invoker invoker = new DefaultInvoker();
invoker.setLocalRepositoryDirectory(new File(mavenProjectLocation));
// replace it with yours
invoker.setMavenHome(new File("/home/admin/apps/apache-maven-3.5.2"));
return invoker;
}
private static InvocationRequest getInvocationRequest(String mavenProjectLocation, List<String> goals) {
InvocationRequest request = new DefaultInvocationRequest();
request.setBaseDirectory(new File(mavenProjectLocation));
request.setGoals(goals);
return request;
}
}
Usage:
String mavenProjectLocation = "/home/admin/projects/maven-sample-project";
List<String> goals = Arrays.asList(MavenRunner.MAVEN_COMMAND_CLEAN, MavenRunner.MAVEN_COMMAND_PACKAGE);
MavenRunner.run(mavenProjectLocation, goals);
I have gradle script which is creating the version in JIRA using the REST API.
But there is jira-rest-java-client also available. I want to use the java library of jira-rest-java-client and wants to do the same stuff in gradle. Can someone provide an example how could I try this.
How to use the jira-rest-java-client library to make connection with JIRA through example?
In Java I am trying to use this JRCJ Library but getting below error through Intellj
import com.atlassian.jira.rest.client.api.JiraRestClient;
import com.atlassian.jira.rest.client.api.domain.*;
import com.atlassian.jira.rest.client.api.domain.input.ComplexIssueInputFieldValue;
import com.atlassian.jira.rest.client.api.domain.input.FieldInput;
import com.atlassian.jira.rest.client.api.domain.input.TransitionInput;
import com.atlassian.jira.rest.client.internal.ServerVersionConstants;
import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory;
import com.google.common.collect.Lists;
import org.codehaus.jettison.json.JSONException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* A sample code how to use JRJC library
*
* #since v0.1
*/
public class Example1 {
private static URI jiraServerUri = URI.create("http://localhost:2990/jira");
private static boolean quiet = false;
public static void main(String[] args) throws URISyntaxException, JSONException, IOException {
parseArgs(args);
final AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
final JiraRestClient restClient = factory.createWithBasicHttpAuthentication(jiraServerUri, "admin", "admin");
try {
final int buildNumber = restClient.getMetadataClient().getServerInfo().claim().getBuildNumber();
// first let's get and print all visible projects (only jira4.3+)
if (buildNumber >= ServerVersionConstants.BN_JIRA_4_3) {
final Iterable<BasicProject> allProjects = restClient.getProjectClient().getAllProjects().claim();
for (BasicProject project : allProjects) {
if (project == TEST){
println(project);}else {
System.out.println("Project" + "Not Found");
}
}
}
// let's now print all issues matching a JQL string (here: all assigned issues)
if (buildNumber >= ServerVersionConstants.BN_JIRA_4_3) {
final SearchResult searchResult = restClient.getSearchClient().searchJql("assignee is not EMPTY").claim();
for (BasicIssue issue : searchResult.getIssues()) {
println(issue.getKey());
}
}
final Issue issue = restClient.getIssueClient().getIssue("TST-7").claim();
println(issue);
// now let's vote for it
restClient.getIssueClient().vote(issue.getVotesUri()).claim();
// now let's watch it
final BasicWatchers watchers = issue.getWatchers();
if (watchers != null) {
restClient.getIssueClient().watch(watchers.getSelf()).claim();
}
// now let's start progress on this issue
final Iterable<Transition> transitions = restClient.getIssueClient().getTransitions(issue.getTransitionsUri()).claim();
final Transition startProgressTransition = getTransitionByName(transitions, "Start Progress");
restClient.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(startProgressTransition.getId()))
.claim();
// and now let's resolve it as Incomplete
final Transition resolveIssueTransition = getTransitionByName(transitions, "Resolve Issue");
final Collection<FieldInput> fieldInputs;
// Starting from JIRA 5, fields are handled in different way -
if (buildNumber > ServerVersionConstants.BN_JIRA_5) {
fieldInputs = Arrays.asList(new FieldInput("resolution", ComplexIssueInputFieldValue.with("name", "Incomplete")));
} else {
fieldInputs = Arrays.asList(new FieldInput("resolution", "Incomplete"));
}
final TransitionInput transitionInput = new TransitionInput(resolveIssueTransition.getId(), fieldInputs, Comment
.valueOf("My comment"));
restClient.getIssueClient().transition(issue.getTransitionsUri(), transitionInput).claim();
}
finally {
restClient.close();
}
}
private static void println(Object o) {
if (!quiet) {
System.out.println(o);
}
}
private static void parseArgs(String[] argsArray) throws URISyntaxException {
final List<String> args = Lists.newArrayList(argsArray);
if (args.contains("-q")) {
quiet = true;
args.remove(args.indexOf("-q"));
}
if (!args.isEmpty()) {
jiraServerUri = new URI(args.get(0));
}
}
private static Transition getTransitionByName(Iterable<Transition> transitions, String transitionName) {
for (Transition transition : transitions) {
if (transition.getName().equals(transitionName)) {
return transition;
}
}
return null;
}
}
Error:
xception in thread "main" java.lang.NoClassDefFoundError: com/atlassian/sal/api/executor/ThreadLocalContextManager
at com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory.create(AsynchronousJiraRestClientFactory.java:35)
at com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory.createWithBasicHttpAuthentication(AsynchronousJiraRestClientFactory.java:42)
at Example1.main(Example1.java:34)
Caused by: java.lang.ClassNotFoundException: com.atlassian.sal.api.executor.ThreadLocalContextManager
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 3 more
Moreover I added the JRJC api,core jar in External Libraries but still getting this error?
Could someone tell me what is the issue or where am I missing something?
compile 'com.atlassian.jira:jira-rest-java-client-core:4.0.0'
compile 'com.atlassian.jira:jira-rest-java-client-api:4.0.0'
Simple connection to JIRA:
JiraRestClient restClient = new AsynchronousJiraRestClientFactory().createWithBasicHttpAuthentication(new URI("https://" + jira_domain),
jira_username, jira_password);
I have some symlinks in my build system that point to jars which I need to build if the jars don't exist. i.e. if the symlinks are dangling. Is there an Ant task or workaround to check that?
As to why I can't include a proper Ant dependency to those jars, the reason is that their build process is lengthy, involving on-the-fly Internet downloads from ftp repositories that take too long and is out of my control.
Ok, so in the end I implemented a custom Ant task (code at the end), that can be used from Ant like this:
<file-pronouncer filePath="path/to/file" retProperty="prop-holding-type-of-that-file"/>
It can then be read with:
<echo message="the file-pronouncer task for file 'path/to/file' returned: ${prop-holding-type-of-that-file}"/>
With the following possible outcomes:
[echo] the file-pronouncer task for file 'a' returned: regular-file
[echo] the file-pronouncer task for file 'b' returned: symlink-ok
[echo] the file-pronouncer task for file 'c' returned: symlink-dangling
[echo] the file-pronouncer task for file 'd' returned: not-exists
code for the FilePronouncer custom Ant task
import java.io.IOException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import java.nio.file.Path;
import java.nio.file.Files;
import java.nio.file.FileSystems;
import java.nio.file.LinkOption;
import java.nio.file.attribute.BasicFileAttributes;
import org.apache.tools.ant.BuildException;
public class FilePronouncer extends Task {
private String filePath = null;
private String retProperty = null;
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getRetProperty() {
return retProperty;
}
public void setRetProperty(String property) {
this.retProperty = property;
}
public void execute() {
try {
Path path = FileSystems.getDefault().getPath(filePath);
boolean fileExists = Files.exists(path, LinkOption.NOFOLLOW_LINKS);
Boolean isSymlink = null;
Boolean filePointedToExists = null;
if (fileExists) {
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
isSymlink = attrs.isSymbolicLink();
if (isSymlink)
filePointedToExists = Files.exists(path);
}
Project project = getProject();
String rv = null;
if (!fileExists)
rv = "not-exists";
else {
if (!isSymlink)
rv = "regular-file";
else {
if (filePointedToExists)
rv = "symlink-ok";
else
rv = "symlink-dangling";
}
}
project.setProperty(retProperty, rv);
} catch (IOException e) {
throw new BuildException(e);
}
}
}
I created an eclipse plugin that will hook into the save action to create a minified javascript file with the goolge closure compiler. See files below.
That worked until eclipse 3.7.2. Unfortunately now in eclipse 4.2.1 it seems that this creates an endless loop sometimes. The job "compile .min.js" (line 64 in ResourceChangedListener.java) seems the be the cause. It results in the case that the workspaced starts to build over and over. I guess this is because that job creates or changes a file triggering the workspace build again, which again triggers the job which triggers the build and so on.
But I can not figure out how to prevent this.
// Activator.java
package closure_compiler_save;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
/**
* The activator class controls the plug-in life cycle
*/
public class Activator extends AbstractUIPlugin {
// The plug-in ID
public static final String PLUGIN_ID = "closure-compiler-save"; //$NON-NLS-1$
// The shared instance
private static Activator plugin;
/**
* The constructor
*/
public Activator() {
}
#Override
public void start(BundleContext context) throws Exception {
super.start(context);
Activator.plugin = this;
ResourceChangedListener listener = new ResourceChangedListener();
ResourcesPlugin.getWorkspace().addResourceChangeListener(listener);
}
#Override
public void stop(BundleContext context) throws Exception {
Activator.plugin = null;
super.stop(context);
}
/**
* Returns the shared instance
*
* #return the shared instance
*/
public static Activator getDefault() {
return plugin;
}
}
// ResourceChangedListener.java
package closure_compiler_save;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
public class ResourceChangedListener implements IResourceChangeListener {
public void resourceChanged(IResourceChangeEvent event) {
if (event.getType() != IResourceChangeEvent.POST_CHANGE)
return;
IResourceDelta delta = event.getDelta();
try {
processDelta(delta);
} catch (CoreException e) {
e.printStackTrace();
}
}
// find out which class files were just built
private void processDelta(IResourceDelta delta) throws CoreException {
IResourceDelta[] kids = delta.getAffectedChildren();
for (IResourceDelta delta2 : kids) {
if (delta2.getAffectedChildren().length == 0) {
if (delta.getKind() != IResourceDelta.CHANGED)
return;
IResource res = delta2.getResource();
if (res.getType() == IResource.FILE && "js".equalsIgnoreCase(res.getFileExtension())) {
if (res.getName().contains("min"))
return;
compile(res);
}
}
processDelta(delta2);
}
}
private void compile(final IResource res) throws CoreException {
final IPath fullPath = res.getFullPath();
final IPath fullLocation = res.getLocation();
final String fileName = fullPath.lastSegment().toString();
final String outputFilename = fileName.substring(0, fileName.lastIndexOf(".")).concat(".min.js");
final String outputPath = fullPath.removeFirstSegments(1).removeLastSegments(1).toString();
final IProject project = res.getProject();
final IFile newFile = project.getFile(outputPath.concat("/".concat(outputFilename)));
Job compileJob = new Job("Compile .min.js") {
public IStatus run(IProgressMonitor monitor) {
byte[] bytes = null;
try {
bytes = CallCompiler.compile(fullLocation.toString(), CallCompiler.SIMPLE_OPTIMIZATION).getBytes();
InputStream source = new ByteArrayInputStream(bytes);
if (!newFile.exists()) {
newFile.create(source, IResource.NONE, null);
} else {
newFile.setContents(source, IResource.NONE, null);
}
} catch (IOException e) {
e.printStackTrace();
} catch (CoreException e) {
e.printStackTrace();
}
return Status.OK_STATUS;
}
};
compileJob.setRule(newFile.getProject()); // this will ensure that no two jobs are writing simultaneously on the same file
compileJob.schedule();
}
}
After I setup a blank eclipse classic environment, started a new eclipse plugin project there and recreated all files it works again partly.
In this environment starting a debug session I can save .js files and .min.js files are created automatically.
So far so good!
But when I install the plugin to my real developing eclipse environment automatic saving does not work.
At least one step further!
Step 2:
There were some files not included in the build obviously needed, like manifest. No idea why they were deselected.
Anyway it seems just setting up a blank eclipse 4 classic and going through the eclipse plugin wizard fixed my original problem. I still would love to know what was the actual problem...