You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@batchee.apache.org by rm...@apache.org on 2015/12/01 23:36:27 UTC

[1/2] incubator-batchee git commit: adding @Documentation on all our components

Repository: incubator-batchee
Updated Branches:
  refs/heads/master e87abcf68 -> 95e199aad


http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/tools/maven-plugin/src/main/java/org/apache/batchee/tools/maven/DocumentationMojo.java
----------------------------------------------------------------------
diff --git a/tools/maven-plugin/src/main/java/org/apache/batchee/tools/maven/DocumentationMojo.java b/tools/maven-plugin/src/main/java/org/apache/batchee/tools/maven/DocumentationMojo.java
index c1df82b..23154d6 100644
--- a/tools/maven-plugin/src/main/java/org/apache/batchee/tools/maven/DocumentationMojo.java
+++ b/tools/maven-plugin/src/main/java/org/apache/batchee/tools/maven/DocumentationMojo.java
@@ -16,43 +16,18 @@
  */
 package org.apache.batchee.tools.maven;
 
+import org.apache.batchee.tools.maven.doc.ComponentDocumentationGenerator;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.FieldVisitor;
 
-import java.beans.Introspector;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-import static org.objectweb.asm.ClassReader.SKIP_CODE;
-import static org.objectweb.asm.ClassReader.SKIP_DEBUG;
-import static org.objectweb.asm.ClassReader.SKIP_FRAMES;
-import static org.objectweb.asm.Opcodes.ASM5;
 
 @Mojo(name = "doc", defaultPhase = LifecyclePhase.PROCESS_CLASSES)
 public class DocumentationMojo extends AbstractMojo {
-    private static final String PROPERTY_MARKER = "Ljavax/batch/api/BatchProperty;";
-    private static final String NAMED_MARKER = "Ljavax/inject/Named;";
-    private static final String INJECT_MARKER = "Ljavax/inject/Inject;";
-    private static final String CONFIGURATION_MARKER = "Lorg/apache/batchee/doc/api/Configuration;";
-
     @Parameter(property = "batchee.classes", defaultValue = "${project.build.outputDirectory}")
     protected File classes;
 
@@ -64,270 +39,11 @@ public class DocumentationMojo extends AbstractMojo {
 
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
-        if (classes == null || !classes.isDirectory()) {
-            getLog().warn((classes != null ? classes.getAbsolutePath() : "null") + " is not a directory, skipping");
-            return;
-        }
-
-        // instantiate the formatter now to avoid to scan for nothing if we can't instantiate it
-        final Formatter formatterInstance = createFormatter();
-
-        // find meta
-        final Map<String, Collection<FieldDoc>> configByComponent = new TreeMap<String, Collection<FieldDoc>>();
-        try {
-            scan(configByComponent, classes);
-        } catch (final IOException e) {
-            throw new MojoExecutionException(e.getMessage(), e);
-        }
-
-        if (configByComponent.isEmpty()) {
-            getLog().warn("Nothing found, maybe adjust <classes>, skipping.");
-            return;
-        }
-
-        // format what we found
-        if (!output.getParentFile().isDirectory() && !output.getParentFile().mkdirs()) {
-            throw new MojoExecutionException("Can't create " + output.getAbsolutePath());
-        }
-        FileWriter writer = null;
-        try {
-            writer = new FileWriter(output);
-            formatterInstance.begin(writer);
-            for (final Map.Entry<String, Collection<FieldDoc>> component : configByComponent.entrySet()) {
-                formatterInstance.beginClass(writer, component.getKey());
-                for (final FieldDoc doc : component.getValue()) {
-                    formatterInstance.add(writer, doc);
-                }
-                formatterInstance.endClass(writer);
-            }
-            formatterInstance.end(writer);
-        } catch (final IOException e) {
-            throw new MojoExecutionException(e.getMessage(), e);
-        } finally {
-            if (writer != null) {
-                try {
-                    writer.close();
-                } catch (final IOException e) {
-                    // no-op
-                }
-            }
-        }
-    }
-
-    private Formatter createFormatter() {
-        if (formatter == null || formatter.startsWith("adoc")) {
-            final int level = "adoc".equals(formatter) || formatter == null ? 1 : Integer.parseInt(formatter.substring("adoc".length()));
-            final String prefix;
-            {
-                final StringBuilder builder = new StringBuilder();
-                for (int i = 0; i < level; i++) {
-                    builder.append("=");
-                }
-                prefix = builder.toString();
-            }
-
-            return new Formatter() {
-                @Override
-                public void begin(final Writer writer) throws IOException {
-                    // no-op
-                }
-
-                @Override
-                public void beginClass(final Writer writer, final String className) throws IOException {
-                    writer.append(prefix).append(" ").append(className).append("\n\n|===\n|Name|Description\n");
-                }
-
-                @Override
-                public void add(final Writer writer, final FieldDoc doc) throws IOException {
-                    writer.append("|").append(doc.getName()).append("|").append(doc.getDoc() == null ? "-" : doc.getDoc()).append("\n");
-                }
-
-                @Override
-                public void endClass(final Writer writer) throws IOException {
-                    writer.append("|===\n\n");
-                }
-
-                @Override
-                public void end(final Writer writer) throws IOException {
-                    // no-op
-                }
-            };
-        }
-        try {
-            return Formatter.class.cast(Thread.currentThread().getContextClassLoader().loadClass(formatter.trim()).newInstance());
-        } catch (final InstantiationException e) {
-            throw new IllegalArgumentException(e);
-        } catch (final IllegalAccessException e) {
-            throw new IllegalArgumentException(e);
-        } catch (final ClassNotFoundException e) {
-            throw new IllegalArgumentException(e);
-        }
-    }
-
-    private void scan(final Map<String, Collection<FieldDoc>> commands, final File file) throws IOException {
-        if (file.isFile()) {
-            if (file.getName().endsWith(".class")) {
-                component(commands, file);
-            } // else we don't care
-        } else if (file.isDirectory()) {
-            final File[] children = file.listFiles();
-            if (children != null) {
-                for (final File child : children) {
-                    scan(commands, child);
-                }
-            }
-        }
-    }
-
-    private String component(final Map<String, Collection<FieldDoc>> commands, final File classFile) throws IOException {
-        InputStream stream = null;
-        try {
-            stream = new FileInputStream(classFile);
-            final ClassReader reader = new ClassReader(stream);
-            reader.accept(new ClassVisitor(ASM5) {
-                private String className;
-                private List<FieldDoc> configs;
-
-                @Override
-                public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) {
-                    className = name.replace('/', '.');
-                }
-
-                @Override
-                public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
-                    final AnnotationVisitor annotationVisitor = super.visitAnnotation(desc, visible);
-                    if (NAMED_MARKER.equals(desc)) {
-                        final int dollar = className.lastIndexOf('$');
-                        if (dollar > 0) {
-                            className = className.substring(dollar + 1);
-                        } else {
-                            final int dot = className.lastIndexOf('.');
-                            if (dot > 0) {
-                                className = className.substring(dot + 1);
-                            }
-                        }
-
-                        className = Introspector.decapitalize(className);
-                        return new AnnotationVisitor(ASM5, annotationVisitor) {
-                            @Override
-                            public void visit(final String name, final Object value) {
-                                super.visit(name, value);
-                                if ("value".equals(name) && String.class.isInstance(value) && !String.class.cast(value).isEmpty()) {
-                                    className = value.toString();
-                                }
-                            }
-                        };
-                    }
-                    return annotationVisitor;
-                }
-
-                @Override
-                public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) {
-                    return new FieldVisitor(ASM5, super.visitField(access, name, desc, signature, value)) {
-                        private boolean marked = false;
-                        private boolean hasInject = false;
-                        private String configName = name;
-                        private String doc = null;
-
-                        @Override
-                        public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
-                            final AnnotationVisitor annotationVisitor = super.visitAnnotation(desc, visible);
-                            if (PROPERTY_MARKER.equals(desc)) {
-                                marked = true;
-                                return new AnnotationVisitor(ASM5, annotationVisitor) {
-                                    @Override
-                                    public void visit(final String name, final Object value) {
-                                        super.visit(name, value);
-                                        if ("name".equals(name) && String.class.isInstance(value) && !String.class.cast(value).isEmpty()) {
-                                            configName = value.toString();
-                                        }
-                                    }
-                                };
-                            }
-                            if (INJECT_MARKER.equals(desc)) {
-                                hasInject = true;
-                                return annotationVisitor;
-                            }
-                            if (CONFIGURATION_MARKER.equals(desc)) {
-                                return new AnnotationVisitor(ASM5, annotationVisitor) {
-                                    @Override
-                                    public void visit(final String name, final Object value) {
-                                        super.visit(name, value);
-                                        if ("value".equals(name) && String.class.isInstance(value) && !String.class.cast(value).isEmpty()) {
-                                            doc = value.toString();
-                                        }
-                                    }
-                                };
-                            }
-                            return annotationVisitor;
-                        }
-
-                        @Override
-                        public void visitEnd() {
-                            super.visitEnd();
-                            if (marked && hasInject) {
-                                if (configs == null) {
-                                    configs = new ArrayList<FieldDoc>();
-                                }
-                                configs.add(new FieldDoc(configName, doc));
-                            }
-                        }
-                    };
-                }
-
-                @Override
-                public void visitEnd() {
-                    super.visitEnd();
-                    if (configs != null) {
-                        Collections.sort(configs);
-                        commands.put(className, configs);
-                    }
-                }
-            }, SKIP_CODE + SKIP_DEBUG + SKIP_FRAMES);
-        } finally {
-            try {
-                if (stream != null) {
-                    stream.close();
-                }
-            } catch (final IOException e) {
-                // no-op
+        new ComponentDocumentationGenerator(classes, output, formatter) {
+            @Override
+            protected void warn(final String s) {
+                getLog().warn(s);
             }
-        }
-        return null;
-    }
-
-    public static class FieldDoc implements Comparable<FieldDoc> {
-        private final String name;
-        private final String doc;
-
-        private FieldDoc(final String name, final String doc) {
-            this.name = name;
-            this.doc = doc;
-        }
-
-        @Override
-        public int compareTo(final FieldDoc o) {
-            return name.compareTo(o.name);
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public String getDoc() {
-            return doc;
-        }
-    }
-
-    public interface Formatter {
-        void begin(Writer writer) throws IOException;
-
-        void beginClass(Writer writer, String className) throws IOException;
-
-        void add(Writer writer, FieldDoc doc) throws IOException;
-
-        void endClass(Writer writer) throws IOException;
-
-        void end(Writer writer) throws IOException;
+        }.execute();
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/tools/maven-plugin/src/main/java/org/apache/batchee/tools/maven/doc/ComponentDocumentationGenerator.java
----------------------------------------------------------------------
diff --git a/tools/maven-plugin/src/main/java/org/apache/batchee/tools/maven/doc/ComponentDocumentationGenerator.java b/tools/maven-plugin/src/main/java/org/apache/batchee/tools/maven/doc/ComponentDocumentationGenerator.java
new file mode 100644
index 0000000..6b8d3af
--- /dev/null
+++ b/tools/maven-plugin/src/main/java/org/apache/batchee/tools/maven/doc/ComponentDocumentationGenerator.java
@@ -0,0 +1,439 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.batchee.tools.maven.doc;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+
+import java.beans.Introspector;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import static org.objectweb.asm.ClassReader.SKIP_CODE;
+import static org.objectweb.asm.ClassReader.SKIP_DEBUG;
+import static org.objectweb.asm.ClassReader.SKIP_FRAMES;
+import static org.objectweb.asm.Opcodes.ASM5;
+
+// NO MAVEN IMPORTS THERE
+public abstract class ComponentDocumentationGenerator {
+    private static final String OBJECT_NAME = "java/lang/Object";
+    private static final String PROPERTY_MARKER = "Ljavax/batch/api/BatchProperty;";
+    private static final String NAMED_MARKER = "Ljavax/inject/Named;";
+    private static final String INJECT_MARKER = "Ljavax/inject/Inject;";
+    private static final String CONFIGURATION_MARKER = "Lorg/apache/batchee/doc/api/Documentation;";
+
+    protected final File classes;
+    protected final File output;
+    protected final String formatter;
+
+    protected ComponentDocumentationGenerator(final File classes, final File output, final String formatter) {
+        this.classes = classes;
+        this.output = output;
+        this.formatter = formatter;
+    }
+
+    public static void main(final String[] args) {
+        new ComponentDocumentationGenerator(new File(args[0]), new File(args[1]), args[2]) {
+            @Override
+            protected void warn(final String s) {
+                System.err.println(s);
+            }
+        }.execute();
+    }
+
+    public void execute() {
+        if (classes == null || !classes.isDirectory()) {
+            warn((classes != null ? classes.getAbsolutePath() : "null") + " is not a directory, skipping");
+            return;
+        }
+
+        // instantiate the formatter now to avoid to scan for nothing if we can't instantiate it
+        final Formatter formatterInstance = createFormatter();
+
+        // find meta
+        final Map<String, ClassDoc> configByComponent = new TreeMap<String, ClassDoc>();
+        try {
+            scan(configByComponent, classes);
+        } catch (final IOException e) {
+            throw new IllegalStateException(e.getMessage(), e);
+        }
+
+        if (configByComponent.isEmpty()) {
+            warn("Nothing found, maybe adjust <classes>, skipping.");
+            return;
+        }
+
+        handleParents(configByComponent);
+
+        // format what we found
+        if (!output.getParentFile().isDirectory() && !output.getParentFile().mkdirs()) {
+            throw new IllegalStateException("Can't create " + output.getAbsolutePath());
+        }
+        FileWriter writer = null;
+        try {
+            writer = new FileWriter(output);
+            formatterInstance.begin(writer);
+            for (final Map.Entry<String, ClassDoc> component : configByComponent.entrySet()) {
+                final ClassDoc value = component.getValue();
+                if (!value.leaf) {
+                    continue;
+                }
+
+                formatterInstance.beginClass(writer, value.name, value.doc);
+                for (final FieldDoc doc : value.configuration) {
+                    formatterInstance.add(writer, doc);
+                }
+                formatterInstance.endClass(writer);
+            }
+            formatterInstance.end(writer);
+        } catch (final IOException e) {
+            throw new IllegalStateException(e.getMessage(), e);
+        } finally {
+            if (writer != null) {
+                try {
+                    writer.close();
+                } catch (final IOException e) {
+                    // no-op
+                }
+            }
+        }
+    }
+
+    protected abstract void warn(String s);
+
+    private void handleParents(final Map<String, ClassDoc> configByComponent) {
+        for (final Map.Entry<String, ClassDoc> component : configByComponent.entrySet()) {
+            String parent = component.getValue().parent;
+            while (parent != null) {
+                final ClassDoc doc = configByComponent.get(parent);
+                if (doc != null) {
+                    component.getValue().configuration.addAll(doc.configuration);
+                    Collections.sort(component.getValue().configuration);
+                    parent = doc.parent;
+                } else {
+                    parent = null;
+                }
+            }
+        }
+    }
+
+    private Formatter createFormatter() {
+        if (formatter == null || formatter.startsWith("adoc")) {
+            final int level = "adoc".equals(formatter) || formatter == null ? 1 : Integer.parseInt(formatter.substring("adoc".length()));
+            final String prefix = buildPrefix('=', level);
+
+            return new Formatter() {
+                @Override
+                public void begin(final Writer writer) throws IOException {
+                    // no-op
+                }
+
+                @Override
+                public void beginClass(final Writer writer, final String className, final String doc) throws IOException {
+                    writer.append(prefix).append(" ").append(className).append("\n\n");
+                    if (doc != null) {
+                        writer.append(doc).append("\n\n");
+                    }
+                    writer.append("|===\n|Name|Description\n");
+                }
+
+                @Override
+                public void add(final Writer writer, final FieldDoc doc) throws IOException {
+                    writer.append("|").append(doc.getName()).append("|").append(doc.getDoc() == null ? "-" : doc.getDoc()).append("\n");
+                }
+
+                @Override
+                public void endClass(final Writer writer) throws IOException {
+                    writer.append("|===\n\n");
+                }
+
+                @Override
+                public void end(final Writer writer) throws IOException {
+                    // no-op
+                }
+            };
+        } else if (formatter.startsWith("md")) {
+            final String prefix = buildPrefix('#', "md".equals(formatter) ? 1 : Integer.parseInt(formatter.substring("md".length())));
+
+            return new Formatter() {
+                @Override
+                public void begin(final Writer writer) throws IOException {
+                    // no-op
+                }
+
+                @Override
+                public void beginClass(final Writer writer, final String className, final String doc) throws IOException {
+                    writer.append(prefix).append(" ").append(className).append("\n\n");
+                    if (doc != null) {
+                        writer.append(doc).append("\n\n");
+                    }
+                }
+
+                @Override
+                public void add(final Writer writer, final FieldDoc doc) throws IOException {
+                    writer.append("* ").append(doc.getName()).append(doc.getDoc() == null ? "" : ": " + doc.getDoc()).append("\n");
+                }
+
+                @Override
+                public void endClass(final Writer writer) throws IOException {
+                    writer.append('\n');
+                }
+
+                @Override
+                public void end(final Writer writer) throws IOException {
+                    // no-op
+                }
+            };
+        }
+        try {
+            return Formatter.class.cast(Thread.currentThread().getContextClassLoader().loadClass(formatter.trim()).newInstance());
+        } catch (final InstantiationException e) {
+            throw new IllegalArgumentException(e);
+        } catch (final IllegalAccessException e) {
+            throw new IllegalArgumentException(e);
+        } catch (final ClassNotFoundException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    private String buildPrefix(final char c, final int level) {
+        final String prefix;
+        {
+            final StringBuilder builder = new StringBuilder();
+            for (int i = 0; i < level; i++) {
+                builder.append(c);
+            }
+            prefix = builder.toString();
+        }
+        return prefix;
+    }
+
+    private void scan(final Map<String, ClassDoc> commands, final File file) throws IOException {
+        if (file.isFile()) {
+            if (file.getName().endsWith(".class")) {
+                component(commands, file);
+            } // else we don't care
+        } else if (file.isDirectory()) {
+            final File[] children = file.listFiles();
+            if (children != null) {
+                for (final File child : children) {
+                    scan(commands, child);
+                }
+            }
+        }
+    }
+
+    private String component(final Map<String, ClassDoc> commands, final File classFile) throws IOException {
+        InputStream stream = null;
+        try {
+            stream = new FileInputStream(classFile);
+            final ClassReader reader = new ClassReader(stream);
+            reader.accept(new ClassVisitor(ASM5) {
+                public boolean isLeaf;
+                private String parentName;
+                private String configName;
+                private String className;
+                private String doc;
+                private List<FieldDoc> configs;
+
+                @Override
+                public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) {
+                    parentName = superName == null || OBJECT_NAME.equals(superName) ? null : superName.replace('/', '.');
+                    className = name.replace('/', '.');
+                    isLeaf = !Modifier.isAbstract(access); // TODO: interfaces?
+                }
+
+                @Override
+                public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
+                    final AnnotationVisitor annotationVisitor = super.visitAnnotation(desc, visible);
+                    if (NAMED_MARKER.equals(desc)) {
+                        configName = className;
+                        final int dollar = configName.lastIndexOf('$');
+                        if (dollar > 0) {
+                            configName = configName.substring(dollar + 1);
+                        } else {
+                            final int dot = configName.lastIndexOf('.');
+                            if (dot > 0) {
+                                configName = configName.substring(dot + 1);
+                            }
+                        }
+
+                        configName = Introspector.decapitalize(configName);
+                        return new AnnotationVisitor(ASM5, annotationVisitor) {
+                            @Override
+                            public void visit(final String name, final Object value) {
+                                super.visit(name, value);
+                                if ("value".equals(name) && String.class.isInstance(value) && !String.class.cast(value).isEmpty()) {
+                                    configName = value.toString();
+                                }
+                            }
+                        };
+                    }
+                    if (CONFIGURATION_MARKER.equals(desc)) {
+                        return new AnnotationVisitor(ASM5, annotationVisitor) {
+                            @Override
+                            public void visit(final String name, final Object value) {
+                                super.visit(name, value);
+                                if ("value".equals(name) && String.class.isInstance(value) && !String.class.cast(value).isEmpty()) {
+                                    doc = value.toString();
+                                }
+                            }
+                        };
+                    }
+                    return annotationVisitor;
+                }
+
+                @Override
+                public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) {
+                    return new FieldVisitor(ASM5, super.visitField(access, name, desc, signature, value)) {
+                        private boolean marked = false;
+                        private boolean hasInject = false;
+                        private String configName = name;
+                        private String doc = null;
+
+                        @Override
+                        public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
+                            final AnnotationVisitor annotationVisitor = super.visitAnnotation(desc, visible);
+                            if (PROPERTY_MARKER.equals(desc)) {
+                                marked = true;
+                                return new AnnotationVisitor(ASM5, annotationVisitor) {
+                                    @Override
+                                    public void visit(final String name, final Object value) {
+                                        super.visit(name, value);
+                                        if ("name".equals(name) && String.class.isInstance(value) && !String.class.cast(value).isEmpty()) {
+                                            configName = value.toString();
+                                        }
+                                    }
+                                };
+                            }
+                            if (INJECT_MARKER.equals(desc)) {
+                                hasInject = true;
+                                return annotationVisitor;
+                            }
+                            if (CONFIGURATION_MARKER.equals(desc)) {
+                                return new AnnotationVisitor(ASM5, annotationVisitor) {
+                                    @Override
+                                    public void visit(final String name, final Object value) {
+                                        super.visit(name, value);
+                                        if ("value".equals(name) && String.class.isInstance(value) && !String.class.cast(value).isEmpty()) {
+                                            doc = value.toString();
+                                        }
+                                    }
+                                };
+                            }
+                            return annotationVisitor;
+                        }
+
+                        @Override
+                        public void visitEnd() {
+                            super.visitEnd();
+                            if (marked && hasInject) {
+                                if (configs == null) {
+                                    configs = new ArrayList<FieldDoc>();
+                                }
+                                configs.add(new FieldDoc(configName, doc));
+                            }
+                        }
+                    };
+                }
+
+                @Override
+                public void visitEnd() {
+                    super.visitEnd();
+                    if (configs != null) {
+                        Collections.sort(configs);
+                        commands.put(className, new ClassDoc(isLeaf, parentName, configName == null ? className: configName, doc, configs));
+                    }
+                }
+            }, SKIP_CODE + SKIP_DEBUG + SKIP_FRAMES);
+        } finally {
+            try {
+                if (stream != null) {
+                    stream.close();
+                }
+            } catch (final IOException e) {
+                // no-op
+            }
+        }
+        return null;
+    }
+
+    public static class ClassDoc {
+        private final boolean leaf;
+        private final String parent;
+        private final String name;
+        private final String doc;
+        private final List<FieldDoc> configuration;
+
+        public ClassDoc(boolean isLeaf, final String parent, final String name,
+                        final String doc,
+                        final List<FieldDoc> configuration) {
+            this.leaf = isLeaf;
+            this.parent = parent;
+            this.name = name;
+            this.doc = doc;
+            this.configuration = configuration;
+        }
+    }
+
+    public static class FieldDoc implements Comparable<FieldDoc> {
+        private final String name;
+        private final String doc;
+
+        private FieldDoc(final String name, final String doc) {
+            this.name = name;
+            this.doc = doc;
+        }
+
+        @Override
+        public int compareTo(final FieldDoc o) {
+            return name.compareTo(o.name);
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getDoc() {
+            return doc;
+        }
+    }
+
+    public interface Formatter {
+        void begin(Writer writer) throws IOException;
+
+        void beginClass(Writer writer, String className, String doc) throws IOException;
+
+        void add(Writer writer, FieldDoc doc) throws IOException;
+
+        void endClass(Writer writer) throws IOException;
+
+        void end(Writer writer) throws IOException;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/tools/maven-plugin/src/test/java/org/apache/batchee/tools/maven/DocumentationMojoTest.java
----------------------------------------------------------------------
diff --git a/tools/maven-plugin/src/test/java/org/apache/batchee/tools/maven/DocumentationMojoTest.java b/tools/maven-plugin/src/test/java/org/apache/batchee/tools/maven/DocumentationMojoTest.java
index 4e4dd66..58b086c 100644
--- a/tools/maven-plugin/src/test/java/org/apache/batchee/tools/maven/DocumentationMojoTest.java
+++ b/tools/maven-plugin/src/test/java/org/apache/batchee/tools/maven/DocumentationMojoTest.java
@@ -16,7 +16,7 @@
  */
 package org.apache.batchee.tools.maven;
 
-import org.apache.batchee.doc.api.Configuration;
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 import org.codehaus.plexus.util.IOUtil;
@@ -33,14 +33,26 @@ import static org.junit.Assert.assertEquals;
 
 public class DocumentationMojoTest {
     @Test
-    public void document() throws MojoFailureException, MojoExecutionException, IOException {
+    public void documentAdoc() throws MojoFailureException, MojoExecutionException, IOException {
         final File out = new File("target/DocumentationMojoTest/output.adoc");
         new DocumentationMojo() {{
             classes = new File("target/test-classes/org/apache/batchee/tools/maven/");
             output = out;
         }}.execute();
         final FileInputStream fis = new FileInputStream(out);
-        assertEquals("= myComponent\n" +
+        assertEquals(
+            "= myChildComponent\n" +
+            "\n" +
+            "a child comp\n" +
+            "\n" +
+            "|===\n" +
+            "|Name|Description\n" +
+            "|config2|2\n" +
+            "|configByDefault|this is an important config\n" +
+            "|expl|this one is less important\n" +
+            "|===\n" +
+            "\n" +
+            "= myComponent\n" +
             "\n" +
             "|===\n" +
             "|Name|Description\n" +
@@ -59,16 +71,47 @@ public class DocumentationMojoTest {
         fis.close();
     }
 
+    @Test
+    public void documentMd() throws MojoFailureException, MojoExecutionException, IOException {
+        final File out = new File("target/DocumentationMojoTest/output.adoc");
+        new DocumentationMojo() {{
+            classes = new File("target/test-classes/org/apache/batchee/tools/maven/");
+            output = out;
+            formatter = "md";
+        }}.execute();
+        final FileInputStream fis = new FileInputStream(out);
+        assertEquals(
+            "# myChildComponent\n" +
+            "\n" +
+            "a child comp\n" +
+            "\n" +
+            "* config2: 2\n" +
+            "* configByDefault: this is an important config\n" +
+            "* expl: this one is less important\n" +
+            "\n" +
+            "# myComponent\n" +
+            "\n" +
+            "* configByDefault: this is an important config\n" +
+            "* expl: this one is less important\n" +
+            "\n" +
+            "# org.apache.batchee.tools.maven.batchlet.SimpleBatchlet\n" +
+            "\n" +
+            "* fail\n" +
+            "* sleep\n" +
+            "\n", IOUtil.toString(fis));
+        fis.close();
+    }
+
     @Named
     public static class MyComponent {
         @Inject
         @BatchProperty
-        @Configuration("this is an important config")
+        @Documentation("this is an important config")
         private String configByDefault;
 
         @Inject
         @BatchProperty(name = "expl")
-        @Configuration("this one is less important")
+        @Documentation("this one is less important")
         private String explicit;
 
         private String ignored1;
@@ -76,4 +119,15 @@ public class DocumentationMojoTest {
         @BatchProperty
         private String ignored;
     }
+
+    @Named
+    @Documentation("a child comp")
+    public static class MyChildComponent extends MyComponent {
+        @Inject
+        @BatchProperty
+        @Documentation("2")
+        private String config2;
+
+        private String ignored2;
+    }
 }



[2/2] incubator-batchee git commit: adding @Documentation on all our components

Posted by rm...@apache.org.
adding @Documentation on all our components


Project: http://git-wip-us.apache.org/repos/asf/incubator-batchee/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-batchee/commit/95e199aa
Tree: http://git-wip-us.apache.org/repos/asf/incubator-batchee/tree/95e199aa
Diff: http://git-wip-us.apache.org/repos/asf/incubator-batchee/diff/95e199aa

Branch: refs/heads/master
Commit: 95e199aad4b5b05ca8a1beb8acca48b4452c45f6
Parents: e87abcf
Author: Romain Manni-Bucau <rm...@gmail.com>
Authored: Tue Dec 1 23:37:09 2015 +0100
Committer: Romain Manni-Bucau <rm...@gmail.com>
Committed: Tue Dec 1 23:37:09 2015 +0100

----------------------------------------------------------------------
 .gitignore                                      |   1 +
 .../org/apache/batchee/beanio/BeanIOReader.java |   8 +
 .../org/apache/batchee/beanio/BeanIOWriter.java |   6 +
 .../batchee/camel/CamelChainItemProcessor.java  |   3 +
 .../batchee/camel/CamelItemProcessor.java       |   5 +
 .../apache/batchee/camel/CamelItemReader.java   |   7 +
 .../apache/batchee/camel/CamelItemWriter.java   |   5 +
 extensions/cdi/pom.xml                          |   8 +-
 .../apache/batchee/csv/CommonsCsvReader.java    |  22 +
 .../apache/batchee/csv/CommonsCsvWriter.java    |  22 +
 .../extras/async/AsynchronousItemProcessor.java |   7 +-
 .../org/apache/batchee/extras/chain/Chain.java  |   5 +
 .../batchee/extras/flat/FlatFileItemReader.java |   6 +
 .../batchee/extras/flat/FlatFileItemWriter.java |   9 +
 .../batchee/extras/jdbc/JdbcBatchlet.java       |   3 +
 .../jdbc/JdbcConnectionConfiguration.java       |   7 +
 .../apache/batchee/extras/jdbc/JdbcReader.java  |   5 +
 .../apache/batchee/extras/jdbc/JdbcWriter.java  |   5 +
 .../extras/jpa/EntityManagerLocator.java        |   3 +
 .../batchee/extras/jpa/JpaItemReader.java       |   8 +
 .../batchee/extras/jpa/JpaItemWriter.java       |   5 +
 .../batchee/extras/stax/StaxItemReader.java     |   6 +
 .../batchee/extras/stax/StaxItemWriter.java     |   8 +
 .../validation/BeanValidationItemProcessor.java |   5 +
 .../apache/batchee/groovy/GroovyBatchlet.java   |   4 +
 .../batchee/groovy/GroovyItemProcessor.java     |   4 +
 .../apache/batchee/groovy/GroovyItemReader.java |   4 +
 .../apache/batchee/groovy/GroovyItemWriter.java |   4 +
 .../hazelcast/HazelcastLockBatchlet.java        |   5 +
 .../HazelcastSynchroInstanceAware.java          |   5 +
 .../hazelcast/HazelcastUnlockBatchlet.java      |   3 +
 .../batchee/jackson/JacksonJSonWriter.java      |   7 +
 .../batchee/jackson/JacksonJsonReader.java      |   6 +
 .../apache/batchee/jsefa/JSefaCsvReader.java    |  13 +
 .../apache/batchee/jsefa/JSefaCsvWriter.java    |  13 +
 .../apache/batchee/jsefa/JSefaFlrReader.java    |   8 +
 .../apache/batchee/jsefa/JSefaFlrWriter.java    |   8 +
 .../org/apache/batchee/jsefa/JSefaReader.java   |  10 +-
 .../org/apache/batchee/jsefa/JSefaWriter.java   |  11 +-
 .../apache/batchee/jsefa/JSefaXmlReader.java    |   8 +
 .../apache/batchee/jsefa/JSefaXmlWriter.java    |   8 +
 .../modelmapper/ModelMapperItemProcessor.java   |   6 +-
 extensions/pom.xml                              |  59 +++
 .../apache/batchee/doc/api/Configuration.java   |  32 --
 .../apache/batchee/doc/api/Documentation.java   |  32 ++
 .../batchee/tools/maven/DocumentationMojo.java  | 296 +------------
 .../doc/ComponentDocumentationGenerator.java    | 439 +++++++++++++++++++
 .../tools/maven/DocumentationMojoTest.java      |  64 ++-
 48 files changed, 880 insertions(+), 338 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 8aba325..988997f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ idea/
 .idea
 .classpath
 .project
+batchee-site-generated

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/beanio/src/main/java/org/apache/batchee/beanio/BeanIOReader.java
----------------------------------------------------------------------
diff --git a/extensions/beanio/src/main/java/org/apache/batchee/beanio/BeanIOReader.java b/extensions/beanio/src/main/java/org/apache/batchee/beanio/BeanIOReader.java
index 7fb72d1..04bb635 100644
--- a/extensions/beanio/src/main/java/org/apache/batchee/beanio/BeanIOReader.java
+++ b/extensions/beanio/src/main/java/org/apache/batchee/beanio/BeanIOReader.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.beanio;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.transaction.CountedReader;
 import org.beanio.BeanReader;
 import org.beanio.BeanReaderErrorHandler;
@@ -28,29 +29,36 @@ import java.io.FileReader;
 import java.io.Serializable;
 import java.util.Locale;
 
+@Documentation("Uses BeanIO to read a file.")
 public class BeanIOReader extends CountedReader implements ItemReader {
     @Inject
     @BatchProperty(name = "file")
+    @Documentation("The file to read")
     protected String filePath;
 
     @Inject
     @BatchProperty(name = "skippedHeaderLines")
+    @Documentation("Number of lines to skip")
     protected int skippedHeaderLines;
 
     @Inject
     @BatchProperty
+    @Documentation("The BeanIO stream name")
     protected String streamName;
 
     @Inject
     @BatchProperty
+    @Documentation("The configuration path in the classpath")
     protected String configuration;
 
     @Inject
     @BatchProperty(name = "locale")
+    @Documentation("The locale to use")
     protected String localeStr;
 
     @Inject
     @BatchProperty(name = "errorHandler")
+    @Documentation("The error handler class (resolved using locator)")
     protected String errorHandlerStr;
 
     private BeanReader reader;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/beanio/src/main/java/org/apache/batchee/beanio/BeanIOWriter.java
----------------------------------------------------------------------
diff --git a/extensions/beanio/src/main/java/org/apache/batchee/beanio/BeanIOWriter.java b/extensions/beanio/src/main/java/org/apache/batchee/beanio/BeanIOWriter.java
index b8a6dbe..f87c94f 100644
--- a/extensions/beanio/src/main/java/org/apache/batchee/beanio/BeanIOWriter.java
+++ b/extensions/beanio/src/main/java/org/apache/batchee/beanio/BeanIOWriter.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.beanio;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.transaction.TransactionalWriter;
 import org.beanio.BeanWriter;
 
@@ -27,21 +28,26 @@ import java.io.File;
 import java.io.Serializable;
 import java.util.List;
 
+@Documentation("Reads a file using BeanIO.")
 public class BeanIOWriter implements ItemWriter {
     @Inject
     @BatchProperty(name = "file")
+    @Documentation("The file to write")
     protected String filePath;
 
     @Inject
     @BatchProperty
+    @Documentation("The BeanIO stream name")
     protected String streamName;
 
     @Inject
     @BatchProperty
+    @Documentation("The configuration path in the classpath")
     protected String configuration;
 
     @Inject
     @BatchProperty
+    @Documentation("The output encoding")
     protected String encoding;
 
     private BeanWriter writer;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/camel/src/main/java/org/apache/batchee/camel/CamelChainItemProcessor.java
----------------------------------------------------------------------
diff --git a/extensions/camel/src/main/java/org/apache/batchee/camel/CamelChainItemProcessor.java b/extensions/camel/src/main/java/org/apache/batchee/camel/CamelChainItemProcessor.java
index de9a642..2d26e41 100644
--- a/extensions/camel/src/main/java/org/apache/batchee/camel/CamelChainItemProcessor.java
+++ b/extensions/camel/src/main/java/org/apache/batchee/camel/CamelChainItemProcessor.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.camel;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.chain.Chain;
 import org.apache.batchee.extras.locator.BeanLocator;
 
@@ -23,9 +24,11 @@ import javax.batch.api.BatchProperty;
 import javax.batch.api.chunk.ItemProcessor;
 import javax.inject.Inject;
 
+@Documentation("A chain of camelItemProcessor")
 public class CamelChainItemProcessor extends Chain<ItemProcessor> implements ItemProcessor {
     @Inject
     @BatchProperty
+    @Documentation("The locator to use to find camel item processors.")
     private String templateLocator;
 
     private BeanLocator locatorInstance;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemProcessor.java
----------------------------------------------------------------------
diff --git a/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemProcessor.java b/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemProcessor.java
index 43c8c45..3a11022 100644
--- a/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemProcessor.java
+++ b/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemProcessor.java
@@ -16,17 +16,22 @@
  */
 package org.apache.batchee.camel;
 
+import org.apache.batchee.doc.api.Documentation;
+
 import javax.batch.api.BatchProperty;
 import javax.batch.api.chunk.ItemProcessor;
 import javax.inject.Inject;
 
+@Documentation("Uses camel producer template to process the incoming item.")
 public class CamelItemProcessor implements ItemProcessor {
     @Inject
     @BatchProperty
+    @Documentation("Endpoint URI")
     private String endpoint;
 
     @Inject
     @BatchProperty
+    @Documentation("The locator to use to find the producer template")
     private String templateLocator;
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemReader.java
----------------------------------------------------------------------
diff --git a/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemReader.java b/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemReader.java
index bf4d289..0816b5e 100644
--- a/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemReader.java
+++ b/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemReader.java
@@ -16,26 +16,33 @@
  */
 package org.apache.batchee.camel;
 
+import org.apache.batchee.doc.api.Documentation;
+
 import javax.batch.api.BatchProperty;
 import javax.batch.api.chunk.ItemReader;
 import javax.inject.Inject;
 import java.io.Serializable;
 
+@Documentation("Uses a camel consumer as reader.")
 public class CamelItemReader implements ItemReader {
     @Inject
     @BatchProperty
+    @Documentation("Endpoint URI")
     private String endpoint;
 
     @Inject
     @BatchProperty(name = "timeout")
+    @Documentation("Timeout after which we consider the consumption is done")
     private String timeoutStr;
 
     @Inject
     @BatchProperty
+    @Documentation("Consumer stream type")
     private String expectedClass;
 
     @Inject
     @BatchProperty
+    @Documentation("Locator for the consumer template")
     private String templateLocator;
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemWriter.java
----------------------------------------------------------------------
diff --git a/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemWriter.java b/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemWriter.java
index 77b9eb3..fe4c6c5 100644
--- a/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemWriter.java
+++ b/extensions/camel/src/main/java/org/apache/batchee/camel/CamelItemWriter.java
@@ -16,19 +16,24 @@
  */
 package org.apache.batchee.camel;
 
+import org.apache.batchee.doc.api.Documentation;
+
 import javax.batch.api.BatchProperty;
 import javax.batch.api.chunk.ItemWriter;
 import javax.inject.Inject;
 import java.io.Serializable;
 import java.util.List;
 
+@Documentation("Uses camel to write processed items.")
 public class CamelItemWriter implements ItemWriter {
     @Inject
     @BatchProperty
+    @Documentation("Endpoint URI")
     private String endpoint;
 
     @Inject
     @BatchProperty
+    @Documentation("Locator for the producer template")
     private String templateLocator;
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/cdi/pom.xml
----------------------------------------------------------------------
diff --git a/extensions/cdi/pom.xml b/extensions/cdi/pom.xml
index c9b9c7b..498e00d 100644
--- a/extensions/cdi/pom.xml
+++ b/extensions/cdi/pom.xml
@@ -31,6 +31,7 @@
     <properties>
         <deltaspike.version>1.5.1</deltaspike.version>
     </properties>
+
     <dependencies>
         <dependency>
             <groupId>org.apache.geronimo.specs</groupId>
@@ -110,13 +111,6 @@
                     <scope>test</scope>
                 </dependency>
 
-                <dependency>
-                    <groupId>org.apache.geronimo.specs</groupId>
-                    <artifactId>geronimo-annotation_1.2_spec</artifactId>
-                    <version>1.0</version>
-                    <scope>test</scope>
-                </dependency>
-
             </dependencies>
         </profile>
     </profiles>

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/commons-csv/src/main/java/org/apache/batchee/csv/CommonsCsvReader.java
----------------------------------------------------------------------
diff --git a/extensions/commons-csv/src/main/java/org/apache/batchee/csv/CommonsCsvReader.java b/extensions/commons-csv/src/main/java/org/apache/batchee/csv/CommonsCsvReader.java
index fe0d244..e6e6f7d 100644
--- a/extensions/commons-csv/src/main/java/org/apache/batchee/csv/CommonsCsvReader.java
+++ b/extensions/commons-csv/src/main/java/org/apache/batchee/csv/CommonsCsvReader.java
@@ -17,6 +17,7 @@
 package org.apache.batchee.csv;
 
 import org.apache.batchee.csv.mapper.DefaultMapper;
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.buffered.IteratorReader;
 import org.apache.batchee.extras.locator.BeanLocator;
 import org.apache.batchee.extras.transaction.CountedReader;
@@ -34,6 +35,7 @@ import java.io.Reader;
 import java.io.Serializable;
 import java.io.UnsupportedEncodingException;
 
+@Documentation("Reads a CSV file using commons-csv.")
 public class CommonsCsvReader extends CountedReader {
     private static final CsvReaderMapper<CSVRecord> NOOP_MAPPER = new CsvReaderMapper<CSVRecord>() {
         @Override
@@ -44,82 +46,102 @@ public class CommonsCsvReader extends CountedReader {
 
     @Inject
     @BatchProperty
+    @Documentation("format to use (Default, RFC4180, Excel, TDF, MySQL)")
     private String format;
 
     @Inject
     @BatchProperty
+    @Documentation("file to read")
     private String input;
 
     @Inject
     @BatchProperty
+    @Documentation("input encoding")
     private String encoding;
 
     @Inject
     @BatchProperty
+    @Documentation("record mapper if mapping is null")
     private String mapper;
 
     @Inject
     @BatchProperty
+    @Documentation("mapping type if mapper is null")
     private String mapping;
 
     @Inject
     @BatchProperty
+    @Documentation("locator to lookup the mapper")
     private String locator;
 
     @Inject
     @BatchProperty
+    @Documentation("is missing column names allowed")
     private String allowMissingColumnNames;
 
     @Inject
     @BatchProperty
+    @Documentation("delimiter of the file")
     private String delimiter;
 
     @Inject
     @BatchProperty
+    @Documentation("quote character")
     private String quoteCharacter;
 
     @Inject
     @BatchProperty
+    @Documentation("quote mode (ALL, MINIMAL, NON_NUMERIC, NONE)")
     private String quoteMode;
 
     @Inject
     @BatchProperty
+    @Documentation("comment marker")
     private String commentMarker;
 
     @Inject
     @BatchProperty
+    @Documentation("escape character")
     private String escapeCharacter;
 
     @Inject
     @BatchProperty
+    @Documentation("should the parser ignore surrounding spaces")
     private String ignoreSurroundingSpaces;
 
     @Inject
     @BatchProperty
+    @Documentation("should empty lines be skipped")
     private String ignoreEmptyLines;
 
     @Inject
     @BatchProperty
+    @Documentation("record separator")
     private String recordSeparator;
 
     @Inject
     @BatchProperty
+    @Documentation("string replacement for null")
     private String nullString;
 
     @Inject
     @BatchProperty
+    @Documentation("header comments")
     private String headerComments;
 
     @Inject
     @BatchProperty
+    @Documentation("headers")
     private String header;
 
     @Inject
     @BatchProperty
+    @Documentation("should headers be skipped")
     private String skipHeaderRecord;
 
     @Inject
     @BatchProperty
+    @Documentation("should headers be used")
     private String readHeaders;
 
     private IteratorReader<CSVRecord> iterator;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/commons-csv/src/main/java/org/apache/batchee/csv/CommonsCsvWriter.java
----------------------------------------------------------------------
diff --git a/extensions/commons-csv/src/main/java/org/apache/batchee/csv/CommonsCsvWriter.java b/extensions/commons-csv/src/main/java/org/apache/batchee/csv/CommonsCsvWriter.java
index 20d6d35..3ab27d1 100644
--- a/extensions/commons-csv/src/main/java/org/apache/batchee/csv/CommonsCsvWriter.java
+++ b/extensions/commons-csv/src/main/java/org/apache/batchee/csv/CommonsCsvWriter.java
@@ -17,6 +17,7 @@
 package org.apache.batchee.csv;
 
 import org.apache.batchee.csv.mapper.DefaultMapper;
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.locator.BeanLocator;
 import org.apache.batchee.extras.transaction.TransactionalWriter;
 import org.apache.commons.csv.CSVFormat;
@@ -30,85 +31,106 @@ import java.io.File;
 import java.io.Serializable;
 import java.util.List;
 
+@Documentation("Writes a CSV file using commons-csv.")
 public class CommonsCsvWriter implements ItemWriter {
     @Inject
     @BatchProperty
+    @Documentation("format to use (Default, RFC4180, Excel, TDF, MySQL)")
     private String format;
 
     @Inject
     @BatchProperty
+    @Documentation("file to write")
     private String output;
 
     @Inject
     @BatchProperty
+    @Documentation("output encoding")
     private String encoding;
 
     @Inject
     @BatchProperty
+    @Documentation("record mapper if mapping is null")
     private String mapper;
 
     @Inject
     @BatchProperty
+    @Documentation("mapping type if mapper is null")
     private String mapping;
 
     @Inject
     @BatchProperty
+    @Documentation("locator to lookup the mapper")
     private String locator;
 
     @Inject
     @BatchProperty
+    @Documentation("is missing column names allowed")
     private String allowMissingColumnNames;
 
     @Inject
     @BatchProperty
+    @Documentation("delimiter of the file")
     private String delimiter;
 
     @Inject
     @BatchProperty
+    @Documentation("quote character")
     private String quoteCharacter;
 
     @Inject
     @BatchProperty
+    @Documentation("quote mode (ALL, MINIMAL, NON_NUMERIC, NONE)")
     private String quoteMode;
 
     @Inject
     @BatchProperty
+    @Documentation("comment marker")
     private String commentMarker;
 
     @Inject
     @BatchProperty
+    @Documentation("escape character")
     private String escapeCharacter;
 
     @Inject
     @BatchProperty
+    @Documentation("should the parser ignore surrounding spaces")
     private String ignoreSurroundingSpaces;
 
     @Inject
     @BatchProperty
+    @Documentation("should empty lines be skipped")
     private String ignoreEmptyLines;
 
     @Inject
     @BatchProperty
+    @Documentation("record separator")
     private String recordSeparator;
 
     @Inject
     @BatchProperty
+    @Documentation("string replacement for null")
     private String nullString;
 
     @Inject
     @BatchProperty
+    @Documentation("header comments")
     private String headerComments;
 
     @Inject
     @BatchProperty
+    @Documentation("headers")
     private String header;
 
     @Inject
     @BatchProperty
+    @Documentation("should headers be skipped")
     private String skipHeaderRecord;
 
     @Inject
     @BatchProperty
+    @Documentation("should headers be written")
     private String writeHeaders;
 
     private CSVPrinter writer;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/async/AsynchronousItemProcessor.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/async/AsynchronousItemProcessor.java b/extensions/extras/src/main/java/org/apache/batchee/extras/async/AsynchronousItemProcessor.java
index 257a13a..902c714 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/async/AsynchronousItemProcessor.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/async/AsynchronousItemProcessor.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.extras.async;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.locator.BeanLocator;
 
 import javax.batch.api.BatchProperty;
@@ -27,20 +28,24 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicInteger;
 
-public class AsynchronousItemProcessor<T> implements ItemProcessor {
+@Documentation("Processes asynchronously the items and send to the write a Future<?>.")
+public class AsynchronousItemProcessor implements ItemProcessor {
     protected ExecutorService es = null;
     protected ItemProcessor delegate = null;
 
     @Inject
     @BatchProperty
+    @Documentation("the pool size, if <= 0 cached threads are used")
     private String poolSize;
 
     @Inject
     @BatchProperty
+    @Documentation("Locator for the delegate processor")
     private String locator;
 
     @Inject
     @BatchProperty
+    @Documentation("The actual processor (delegate)")
     private String delegateRef;
 
     protected ExecutorService getExecutor() {

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/chain/Chain.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/chain/Chain.java b/extensions/extras/src/main/java/org/apache/batchee/extras/chain/Chain.java
index bc03f9a..fe84653 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/chain/Chain.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/chain/Chain.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.extras.chain;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.locator.BeanLocator;
 
 import javax.batch.api.BatchProperty;
@@ -27,18 +28,22 @@ import java.util.Collection;
 public abstract class Chain<T> {
     @Inject
     @BatchProperty
+    @Documentation("The locator to use to create chain components")
     protected String locator;
 
     @Inject
     @BatchProperty
+    @Documentation("The list of components of the chain")
     protected String chain;
 
     @Inject
     @BatchProperty
+    @Documentation("The separator to use in chain string (default to ',')")
     protected String separator;
 
     @Inject
     @BatchProperty
+    @Documentation("Should release phase of the lifecycle be called (default to false), use true for @Dependent beans.")
     protected String forceRelease;
 
     private Collection<BeanLocator.LocatorInstance<T>> runtimeChain = new ArrayList<BeanLocator.LocatorInstance<T>>();

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/flat/FlatFileItemReader.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/flat/FlatFileItemReader.java b/extensions/extras/src/main/java/org/apache/batchee/extras/flat/FlatFileItemReader.java
index a87cd8f..dca3cb7 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/flat/FlatFileItemReader.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/flat/FlatFileItemReader.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.extras.flat;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.locator.BeanLocator;
 import org.apache.batchee.extras.transaction.CountedReader;
 
@@ -28,21 +29,26 @@ import java.io.File;
 import java.io.FileReader;
 import java.io.Serializable;
 
+@Documentation("Reads a flat file.")
 public class FlatFileItemReader extends CountedReader implements ItemReader {
     @Inject
     @BatchProperty
+    @Documentation("Locator to find line mapper")
     private String locator;
 
     @Inject
     @BatchProperty
+    @Documentation("The line mapper implementation or reference (see locator)")
     private String lineMapper;
 
     @Inject
     @BatchProperty
+    @Documentation("Input file path")
     private String input;
 
     @Inject
     @BatchProperty(name = "comments")
+    @Documentation("Comments prefix marker (default #)")
     private String commentStr;
 
     private BufferedReader reader = null;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/flat/FlatFileItemWriter.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/flat/FlatFileItemWriter.java b/extensions/extras/src/main/java/org/apache/batchee/extras/flat/FlatFileItemWriter.java
index dd4b46e..862823c 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/flat/FlatFileItemWriter.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/flat/FlatFileItemWriter.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.extras.flat;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.transaction.TransactionalWriter;
 
 import javax.batch.api.BatchProperty;
@@ -26,17 +27,21 @@ import java.io.File;
 import java.io.Serializable;
 import java.util.List;
 
+@Documentation("Writes a flat file.")
 public class FlatFileItemWriter implements ItemWriter {
     @Inject
     @BatchProperty
+    @Documentation("output file path")
     private String output;
 
     @Inject
     @BatchProperty
+    @Documentation("output file encoding")
     private String encoding;
 
     @Inject
     @BatchProperty(name = "line.separator")
+    @Documentation("line separator to use, default is OS dependent")
     private String lineSeparator;
 
     private TransactionalWriter writer = null;
@@ -52,6 +57,10 @@ public class FlatFileItemWriter implements ItemWriter {
         }
         if (lineSeparator == null) {
             lineSeparator = System.getProperty("line.separator", "\n");
+        } else if ("\\n".equals(lineSeparator)) {
+            lineSeparator = "\n";
+        } else if ("\\r\\n".equals(lineSeparator)) {
+            lineSeparator = "\r\n";
         }
 
         writer = new TransactionalWriter(file, encoding, checkpoint);

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcBatchlet.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcBatchlet.java b/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcBatchlet.java
index 008ccac..197ebc6 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcBatchlet.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcBatchlet.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.extras.jdbc;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.transaction.integration.Synchronizations;
 
 import javax.batch.api.BatchProperty;
@@ -24,9 +25,11 @@ import javax.inject.Inject;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 
+@Documentation("Executes an update or delete query.")
 public class JdbcBatchlet extends JdbcConnectionConfiguration implements Batchlet {
     @Inject
     @BatchProperty
+    @Documentation("The update query to execute (UPDATE or DELETE)")
     private String sql;
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcConnectionConfiguration.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcConnectionConfiguration.java b/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcConnectionConfiguration.java
index 085ea98..fe1a7f5 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcConnectionConfiguration.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcConnectionConfiguration.java
@@ -16,6 +16,8 @@
  */
 package org.apache.batchee.extras.jdbc;
 
+import org.apache.batchee.doc.api.Documentation;
+
 import javax.batch.api.BatchProperty;
 import javax.batch.operations.BatchRuntimeException;
 import javax.inject.Inject;
@@ -27,22 +29,27 @@ import java.sql.DriverManager;
 public abstract class JdbcConnectionConfiguration {
     @Inject
     @BatchProperty
+    @Documentation("The JNDI name of the datasource")
     private String jndi;
 
     @Inject
     @BatchProperty
+    @Documentation("The datasource driver to use if jndi is null")
     protected String driver;
 
     @Inject
     @BatchProperty
+    @Documentation("The datasource url to use if jndi is null")
     protected String url;
 
     @Inject
     @BatchProperty
+    @Documentation("The datasource user to use if jndi is null")
     protected String user;
 
     @Inject
     @BatchProperty
+    @Documentation("The datasource password to use if jndi is null")
     protected String password;
 
     protected Connection connection() throws Exception {

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcReader.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcReader.java b/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcReader.java
index bbf9fee..2143f8e 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcReader.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcReader.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.extras.jdbc;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.locator.BeanLocator;
 
 import javax.batch.api.BatchProperty;
@@ -27,17 +28,21 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.util.LinkedList;
 
+@Documentation("Reads data from a SQL query")
 public class JdbcReader extends JdbcConnectionConfiguration implements ItemReader {
     @Inject
     @BatchProperty(name = "mapper")
+    @Documentation("The ResultSet mapper")
     private String mapperStr;
 
     @Inject
     @BatchProperty
+    @Documentation("The locator to lookup the mapper")
     private String locator;
 
     @Inject
     @BatchProperty
+    @Documentation("The query to execute to find data")
     private String query;
 
     private LinkedList<Object> items;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcWriter.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcWriter.java b/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcWriter.java
index e23ed54..469809c 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcWriter.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/jdbc/JdbcWriter.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.extras.jdbc;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.locator.BeanLocator;
 import org.apache.batchee.extras.transaction.integration.Synchronizations;
 
@@ -27,17 +28,21 @@ import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.util.List;
 
+@Documentation("Store the items in a database.")
 public class JdbcWriter extends JdbcConnectionConfiguration implements ItemWriter {
     @Inject
     @BatchProperty
+    @Documentation("The locator to lookup the mapper")
     private String locator;
 
     @Inject
     @BatchProperty(name = "mapper")
+    @Documentation("The mapper to convert items to JDBC domain")
     private String mapperStr;
 
     @Inject
     @BatchProperty
+    @Documentation("The update query")
     private String sql;
 
     private BeanLocator.LocatorInstance<ObjectMapper> mapper;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/EntityManagerLocator.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/EntityManagerLocator.java b/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/EntityManagerLocator.java
index 11857d0..8cf1c22 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/EntityManagerLocator.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/EntityManagerLocator.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.extras.jpa;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.locator.BeanLocator;
 
 import javax.batch.api.BatchProperty;
@@ -27,10 +28,12 @@ import javax.persistence.EntityManager;
 public class EntityManagerLocator {
     @Inject
     @BatchProperty
+    @Documentation("The reference of qualified name of the proviedr for the entity manager")
     protected String entityManagerProvider;
 
     @Inject
     @BatchProperty
+    @Documentation("The locator to use to find the entity manager provider")
     protected String locator;
 
     protected BeanLocator.LocatorInstance<EntityManagerProvider> emProvider;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/JpaItemReader.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/JpaItemReader.java b/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/JpaItemReader.java
index a2a1a86..6273047 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/JpaItemReader.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/JpaItemReader.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.extras.jpa;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.locator.BeanLocator;
 
 import javax.batch.api.BatchProperty;
@@ -29,29 +30,36 @@ import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
 
+@Documentation("Read JPA entities from a query.")
 public class JpaItemReader extends EntityManagerLocator implements ItemReader {
     @Inject
     @BatchProperty
+    @Documentation("The parameter provider ref or qualified name")
     private String parameterProvider;
 
     @Inject
     @BatchProperty
+    @Documentation("The named query to execute")
     private String namedQuery;
 
     @Inject
     @BatchProperty
+    @Documentation("The query to execute if the named query is empty")
     private String query;
 
     @Inject
     @BatchProperty
+    @Documentation("Pagination size")
     private String pageSize;
 
     @Inject
     @BatchProperty
+    @Documentation("Should entities be detached (default false)")
     private String detachEntities;
 
     @Inject
     @BatchProperty
+    @Documentation("Should JPA transaction be used (default false)")
     private String jpaTransaction;
 
     private int page = 10;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/JpaItemWriter.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/JpaItemWriter.java b/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/JpaItemWriter.java
index 3c4f12a..12146c5 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/JpaItemWriter.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/jpa/JpaItemWriter.java
@@ -16,6 +16,8 @@
  */
 package org.apache.batchee.extras.jpa;
 
+import org.apache.batchee.doc.api.Documentation;
+
 import javax.batch.api.BatchProperty;
 import javax.batch.api.chunk.ItemWriter;
 import javax.inject.Inject;
@@ -23,13 +25,16 @@ import javax.persistence.EntityManager;
 import java.io.Serializable;
 import java.util.List;
 
+@Documentation("Write all items using JPA")
 public class JpaItemWriter  extends EntityManagerLocator implements ItemWriter {
     @Inject
     @BatchProperty
+    @Documentation("If set to true merge() will be used instead of persist()")
     private String useMerge;
 
     @Inject
     @BatchProperty
+    @Documentation("Should JPA transaction be used (default false)")
     private String jpaTransaction;
 
     private boolean merge;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/stax/StaxItemReader.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/stax/StaxItemReader.java b/extensions/extras/src/main/java/org/apache/batchee/extras/stax/StaxItemReader.java
index 447b1dd..d9bf9f7 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/stax/StaxItemReader.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/stax/StaxItemReader.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.extras.stax;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.transaction.CountedReader;
 import org.apache.batchee.extras.stax.util.JAXBContextFactory;
 
@@ -36,21 +37,26 @@ import java.io.FileNotFoundException;
 import java.io.InputStream;
 import java.io.Serializable;
 
+@Documentation("Reads XML items using StAX.")
 public class StaxItemReader extends CountedReader implements ItemReader {
     @Inject
     @BatchProperty
+    @Documentation("JAXB type(s) to instantiate for items, supports CSV values")
     private String marshallingClasses;
 
     @Inject
     @BatchProperty
+    @Documentation("JAXB package if needed (optional)")
     private String marshallingPackage;
 
     @Inject
     @BatchProperty
+    @Documentation("Tag to match - others are ignored")
     private String tag;
 
     @Inject
     @BatchProperty
+    @Documentation("Input file path")
     private String input;
 
     private XMLEventReader reader;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/stax/StaxItemWriter.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/stax/StaxItemWriter.java b/extensions/extras/src/main/java/org/apache/batchee/extras/stax/StaxItemWriter.java
index 9ecbee6..d21915c 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/stax/StaxItemWriter.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/stax/StaxItemWriter.java
@@ -16,6 +16,7 @@
  */
 package org.apache.batchee.extras.stax;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.stax.util.JAXBContextFactory;
 import org.apache.batchee.extras.stax.util.SAXStAXHandler;
 import org.apache.batchee.extras.transaction.TransactionalWriter;
@@ -33,29 +34,36 @@ import java.io.File;
 import java.io.Serializable;
 import java.util.List;
 
+@Documentation("Write a file using StAX")
 public class StaxItemWriter implements ItemWriter {
     @Inject
     @BatchProperty(name = "marshallingClasses")
+    @Documentation("JAXB type(s) to instantiate for items, supports CSV values")
     private String marshallingClasses;
 
     @Inject
     @BatchProperty(name = "marshallingPackage")
+    @Documentation("JAXB package if needed (optional)")
     private String marshallingPackage;
 
     @Inject
     @BatchProperty(name = "rootTag")
+    @Documentation("output root tag")
     private String rootTag;
 
     @Inject
     @BatchProperty(name = "encoding")
+    @Documentation("output encoding")
     private String encoding;
 
     @Inject
     @BatchProperty(name = "version")
+    @Documentation("XML document version")
     private String version;
 
     @Inject
     @BatchProperty(name = "output")
+    @Documentation("output file path")
     private String output;
 
     private Marshaller marshaller;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/extras/src/main/java/org/apache/batchee/extras/validation/BeanValidationItemProcessor.java
----------------------------------------------------------------------
diff --git a/extensions/extras/src/main/java/org/apache/batchee/extras/validation/BeanValidationItemProcessor.java b/extensions/extras/src/main/java/org/apache/batchee/extras/validation/BeanValidationItemProcessor.java
index 09847bc..10678de 100644
--- a/extensions/extras/src/main/java/org/apache/batchee/extras/validation/BeanValidationItemProcessor.java
+++ b/extensions/extras/src/main/java/org/apache/batchee/extras/validation/BeanValidationItemProcessor.java
@@ -16,6 +16,8 @@
  */
 package org.apache.batchee.extras.validation;
 
+import org.apache.batchee.doc.api.Documentation;
+
 import javax.batch.api.BatchProperty;
 import javax.batch.api.chunk.ItemProcessor;
 import javax.inject.Inject;
@@ -27,13 +29,16 @@ import javax.validation.Validation;
 import javax.validation.Validator;
 import java.util.Set;
 
+@Documentation("Uses bean validation to validate incoming items.")
 public class BeanValidationItemProcessor implements ItemProcessor {
     @Inject
     @BatchProperty
+    @Documentation("optional bean validation group to validate")
     private String group;
 
     @Inject
     @BatchProperty
+    @Documentation("whether a validation failure throws a ConstraintViolationException or just returns null")
     private String skipNotValidated;
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyBatchlet.java
----------------------------------------------------------------------
diff --git a/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyBatchlet.java b/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyBatchlet.java
index 0a3928d..3932ef7 100644
--- a/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyBatchlet.java
+++ b/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyBatchlet.java
@@ -16,15 +16,19 @@
  */
 package org.apache.batchee.groovy;
 
+import org.apache.batchee.doc.api.Documentation;
+
 import javax.batch.api.BatchProperty;
 import javax.batch.api.Batchlet;
 import javax.batch.runtime.context.JobContext;
 import javax.batch.runtime.context.StepContext;
 import javax.inject.Inject;
 
+@Documentation("Reads and executes a batchlet from a groovy script")
 public class GroovyBatchlet implements Batchlet {
     @Inject
     @BatchProperty
+    @Documentation("The script to execute")
     private String scriptPath;
 
     @Inject

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemProcessor.java
----------------------------------------------------------------------
diff --git a/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemProcessor.java b/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemProcessor.java
index 921e171..7dcb39d 100644
--- a/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemProcessor.java
+++ b/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemProcessor.java
@@ -16,15 +16,19 @@
  */
 package org.apache.batchee.groovy;
 
+import org.apache.batchee.doc.api.Documentation;
+
 import javax.batch.api.BatchProperty;
 import javax.batch.api.chunk.ItemProcessor;
 import javax.batch.runtime.context.JobContext;
 import javax.batch.runtime.context.StepContext;
 import javax.inject.Inject;
 
+@Documentation("Reads and executes a processor from a groovy script")
 public class GroovyItemProcessor implements ItemProcessor {
     @Inject
     @BatchProperty
+    @Documentation("The script to execute")
     private String scriptPath;
 
     @Inject

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemReader.java
----------------------------------------------------------------------
diff --git a/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemReader.java b/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemReader.java
index 692352f..5d6191a 100644
--- a/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemReader.java
+++ b/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemReader.java
@@ -16,6 +16,8 @@
  */
 package org.apache.batchee.groovy;
 
+import org.apache.batchee.doc.api.Documentation;
+
 import javax.batch.api.BatchProperty;
 import javax.batch.api.chunk.ItemReader;
 import javax.batch.runtime.context.JobContext;
@@ -23,9 +25,11 @@ import javax.batch.runtime.context.StepContext;
 import javax.inject.Inject;
 import java.io.Serializable;
 
+@Documentation("Reads and executes a reader from a groovy script")
 public class GroovyItemReader implements ItemReader {
     @Inject
     @BatchProperty
+    @Documentation("The script to execute")
     private String scriptPath;
 
     @Inject

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemWriter.java
----------------------------------------------------------------------
diff --git a/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemWriter.java b/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemWriter.java
index 173d7a9..0132e6e 100644
--- a/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemWriter.java
+++ b/extensions/groovy/src/main/java/org/apache/batchee/groovy/GroovyItemWriter.java
@@ -16,6 +16,8 @@
  */
 package org.apache.batchee.groovy;
 
+import org.apache.batchee.doc.api.Documentation;
+
 import javax.batch.api.BatchProperty;
 import javax.batch.api.chunk.ItemWriter;
 import javax.batch.runtime.context.JobContext;
@@ -24,9 +26,11 @@ import javax.inject.Inject;
 import java.io.Serializable;
 import java.util.List;
 
+@Documentation("Reads and executes a writer from a groovy script")
 public class GroovyItemWriter implements ItemWriter {
     @Inject
     @BatchProperty
+    @Documentation("The script to execute")
     private String scriptPath;
 
     @Inject

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastLockBatchlet.java
----------------------------------------------------------------------
diff --git a/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastLockBatchlet.java b/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastLockBatchlet.java
index a27c50f..e10e2d9 100644
--- a/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastLockBatchlet.java
+++ b/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastLockBatchlet.java
@@ -16,18 +16,23 @@
  */
 package org.apache.batchee.hazelcast;
 
+import org.apache.batchee.doc.api.Documentation;
+
 import javax.batch.api.BatchProperty;
 import javax.batch.api.Batchlet;
 import javax.inject.Inject;
 import java.util.concurrent.TimeUnit;
 
+@Documentation("Obtain a hazelcast lock")
 public class HazelcastLockBatchlet extends HazelcastSynchroInstanceAware implements Batchlet {
     @Inject
     @BatchProperty
+    @Documentation("The duration this task can wait to get the lock")
     protected String tryDuration;
 
     @Inject
     @BatchProperty
+    @Documentation("The duration unit associated to tryDuration")
     protected String tryDurationUnit;
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastSynchroInstanceAware.java
----------------------------------------------------------------------
diff --git a/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastSynchroInstanceAware.java b/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastSynchroInstanceAware.java
index 3fbed63..71f5742 100644
--- a/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastSynchroInstanceAware.java
+++ b/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastSynchroInstanceAware.java
@@ -18,6 +18,7 @@ package org.apache.batchee.hazelcast;
 
 import com.hazelcast.core.HazelcastInstance;
 import com.hazelcast.core.ILock;
+import org.apache.batchee.doc.api.Documentation;
 
 import javax.batch.api.BatchProperty;
 import javax.inject.Inject;
@@ -26,18 +27,22 @@ import java.io.IOException;
 public class HazelcastSynchroInstanceAware {
     @Inject
     @BatchProperty
+    @Documentation("The hazelcast instance name")
     protected String instanceName;
 
     @Inject
     @BatchProperty
+    @Documentation("The hazelcast xml configuration")
     protected String xmlConfiguration;
 
     @Inject
     @BatchProperty
+    @Documentation("Is the instance local, if false the component will create a client")
     protected String local;
 
     @Inject
     @BatchProperty
+    @Documentation("The lock name to use")
     protected String lockName;
 
     protected HazelcastInstance instance() throws IOException {

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastUnlockBatchlet.java
----------------------------------------------------------------------
diff --git a/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastUnlockBatchlet.java b/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastUnlockBatchlet.java
index e060591..c1b1ac2 100644
--- a/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastUnlockBatchlet.java
+++ b/extensions/hazelcast/src/main/java/org/apache/batchee/hazelcast/HazelcastUnlockBatchlet.java
@@ -16,8 +16,11 @@
  */
 package org.apache.batchee.hazelcast;
 
+import org.apache.batchee.doc.api.Documentation;
+
 import javax.batch.api.Batchlet;
 
+@Documentation("Unlock a hazelcast lock")
 public class HazelcastUnlockBatchlet extends HazelcastSynchroInstanceAware implements Batchlet {
     @Override
     public String process() throws Exception {

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/jackson/src/main/java/org/apache/batchee/jackson/JacksonJSonWriter.java
----------------------------------------------------------------------
diff --git a/extensions/jackson/src/main/java/org/apache/batchee/jackson/JacksonJSonWriter.java b/extensions/jackson/src/main/java/org/apache/batchee/jackson/JacksonJSonWriter.java
index a2b96c7..81e0dff 100644
--- a/extensions/jackson/src/main/java/org/apache/batchee/jackson/JacksonJSonWriter.java
+++ b/extensions/jackson/src/main/java/org/apache/batchee/jackson/JacksonJSonWriter.java
@@ -18,6 +18,7 @@ package org.apache.batchee.jackson;
 
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.transaction.TransactionalWriter;
 
 import javax.batch.api.BatchProperty;
@@ -28,25 +29,31 @@ import java.io.File;
 import java.io.Serializable;
 import java.util.List;
 
+@Documentation("Write a JSON file using jackson")
 public class JacksonJSonWriter implements ItemWriter {
     @Inject
     @BatchProperty
+    @Documentation("output file")
     private String file;
 
     @Inject
     @BatchProperty
+    @Documentation("output encoding")
     private String encoding;
 
     @Inject
     @BatchProperty
+    @Documentation("DeserializationFeature and SerializationFeature comma separated key-value configurations")
     private String configuration;
 
     @Inject
     @BatchProperty
+    @Documentation("is the array wrapped in an object or not")
     private String skipRoot;
 
     @Inject
     @BatchProperty
+    @Documentation("how to generate field names for each item, default uses item1, item2, ...")
     private String fieldNameGeneratorClass;
 
     private JsonGenerator generator;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/jackson/src/main/java/org/apache/batchee/jackson/JacksonJsonReader.java
----------------------------------------------------------------------
diff --git a/extensions/jackson/src/main/java/org/apache/batchee/jackson/JacksonJsonReader.java b/extensions/jackson/src/main/java/org/apache/batchee/jackson/JacksonJsonReader.java
index e4486d3..e2cf9d5 100644
--- a/extensions/jackson/src/main/java/org/apache/batchee/jackson/JacksonJsonReader.java
+++ b/extensions/jackson/src/main/java/org/apache/batchee/jackson/JacksonJsonReader.java
@@ -19,6 +19,7 @@ package org.apache.batchee.jackson;
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonToken;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.batchee.doc.api.Documentation;
 import org.apache.batchee.extras.transaction.CountedReader;
 
 import javax.batch.api.BatchProperty;
@@ -26,21 +27,26 @@ import javax.inject.Inject;
 import java.io.File;
 import java.io.Serializable;
 
+@Documentation("Reads a JSON file using jackson.")
 public class JacksonJsonReader extends CountedReader {
     @Inject
     @BatchProperty
+    @Documentation("Incoming file")
     private String file;
 
     @Inject
     @BatchProperty
+    @Documentation("Type to instantiate")
     private String type;
 
     @Inject
     @BatchProperty
+    @Documentation("DeserializationFeature and SerializationFeature comma separated key-value configurations")
     private String configuration;
 
     @Inject
     @BatchProperty
+    @Documentation("Should root be skipped (default: true)")
     private String skipRoot;
 
     private JsonParser parser;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaCsvReader.java
----------------------------------------------------------------------
diff --git a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaCsvReader.java b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaCsvReader.java
index 170ff54..6939571 100644
--- a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaCsvReader.java
+++ b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaCsvReader.java
@@ -18,53 +18,66 @@ package org.apache.batchee.jsefa;
 
 import net.sf.jsefa.Deserializer;
 import net.sf.jsefa.csv.CsvIOFactory;
+import org.apache.batchee.doc.api.Documentation;
 
 import javax.batch.api.BatchProperty;
 import javax.inject.Inject;
 
+@Documentation("Reads a CSV file using JSefa.")
 public class JSefaCsvReader extends JSefaReader {
     @Inject
     @BatchProperty
+    @Documentation("Which ref or implementation to use to filter lines")
     private String lineFilter;
 
     @Inject
     @BatchProperty
+    @Documentation("low level configuration implementation")
     private String lowLevelConfiguration;
 
     @Inject
     @BatchProperty
+    @Documentation("if not using a custom line filter how many lines to filter")
     private String lineFilterLimit;
 
     @Inject
     @BatchProperty
+    @Documentation("record delimiter")
     private String specialRecordDelimiter;
 
     @Inject
     @BatchProperty
+    @Documentation("EOL")
     private String lineBreak;
 
     @Inject
     @BatchProperty
+    @Documentation("which string to use for null values")
     private String defaultNoValueString;
 
     @Inject
     @BatchProperty
+    @Documentation("quote mode (ALWAYS, ON_DEMAND, NEVER, DEFAULT)")
     private String defaultQuoteMode;
 
     @Inject
     @BatchProperty
+    @Documentation("field delimiter")
     private String fieldDelimiter;
 
     @Inject
     @BatchProperty
+    @Documentation("quote charater to use")
     private String quoteCharacter;
 
     @Inject
     @BatchProperty
+    @Documentation("escape mode (ESCAPE_CHARACTER, DOUBLING)")
     private String quoteCharacterEscapeMode;
 
     @Inject
     @BatchProperty
+    @Documentation("should deliimter be used after last field")
     private String useDelimiterAfterLastField;
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaCsvWriter.java
----------------------------------------------------------------------
diff --git a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaCsvWriter.java b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaCsvWriter.java
index 4db1025..502dd5f 100644
--- a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaCsvWriter.java
+++ b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaCsvWriter.java
@@ -18,53 +18,66 @@ package org.apache.batchee.jsefa;
 
 import net.sf.jsefa.Serializer;
 import net.sf.jsefa.csv.CsvIOFactory;
+import org.apache.batchee.doc.api.Documentation;
 
 import javax.batch.api.BatchProperty;
 import javax.inject.Inject;
 
+@Documentation("Writes a CSV file using JSefa.")
 public class JSefaCsvWriter extends JSefaWriter {
     @Inject
     @BatchProperty
+    @Documentation("Which ref or implementation to use to filter lines")
     private String lineFilter;
 
     @Inject
     @BatchProperty
+    @Documentation("low level configuration implementation")
     private String lowLevelConfiguration;
 
     @Inject
     @BatchProperty
+    @Documentation("if not using a custom line filter how many lines to filter")
     private String lineFilterLimit;
 
     @Inject
     @BatchProperty
+    @Documentation("record delimiter")
     private String specialRecordDelimiter;
 
     @Inject
     @BatchProperty
+    @Documentation("EOL")
     private String lineBreak;
 
     @Inject
     @BatchProperty
+    @Documentation("which string to use for null values")
     private String defaultNoValueString;
 
     @Inject
     @BatchProperty
+    @Documentation("quote mode (ALWAYS, ON_DEMAND, NEVER, DEFAULT)")
     private String defaultQuoteMode;
 
     @Inject
     @BatchProperty
+    @Documentation("field delimiter")
     private String fieldDelimiter;
 
     @Inject
     @BatchProperty
+    @Documentation("quote charater to use")
     private String quoteCharacter;
 
     @Inject
     @BatchProperty
+    @Documentation("escape mode (ESCAPE_CHARACTER, DOUBLING)")
     private String quoteCharacterEscapeMode;
 
     @Inject
     @BatchProperty
+    @Documentation("should deliimter be used after last field")
     private String useDelimiterAfterLastField;
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaFlrReader.java
----------------------------------------------------------------------
diff --git a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaFlrReader.java b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaFlrReader.java
index 27f57fc..5a7841b 100644
--- a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaFlrReader.java
+++ b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaFlrReader.java
@@ -18,33 +18,41 @@ package org.apache.batchee.jsefa;
 
 import net.sf.jsefa.Deserializer;
 import net.sf.jsefa.flr.FlrIOFactory;
+import org.apache.batchee.doc.api.Documentation;
 
 import javax.batch.api.BatchProperty;
 import javax.inject.Inject;
 
+@Documentation("Reads a FLR file using JSefa.")
 public class JSefaFlrReader extends JSefaReader {
     @Inject
     @BatchProperty
+    @Documentation("Which ref or implementation to use to filter lines")
     private String lineFilter;
 
     @Inject
     @BatchProperty
+    @Documentation("low level configuration implementation")
     private String lowLevelConfiguration;
 
     @Inject
     @BatchProperty
+    @Documentation("if not using a custom line filter how many lines to filter")
     private String lineFilterLimit;
 
     @Inject
     @BatchProperty
+    @Documentation("record delimiter")
     private String specialRecordDelimiter;
 
     @Inject
     @BatchProperty
+    @Documentation("EOL")
     private String lineBreak;
 
     @Inject
     @BatchProperty
+    @Documentation("pad character")
     private String defaultPadCharacter;
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaFlrWriter.java
----------------------------------------------------------------------
diff --git a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaFlrWriter.java b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaFlrWriter.java
index 53aa5a4..0e66da7 100644
--- a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaFlrWriter.java
+++ b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaFlrWriter.java
@@ -18,33 +18,41 @@ package org.apache.batchee.jsefa;
 
 import net.sf.jsefa.Serializer;
 import net.sf.jsefa.flr.FlrIOFactory;
+import org.apache.batchee.doc.api.Documentation;
 
 import javax.batch.api.BatchProperty;
 import javax.inject.Inject;
 
+@Documentation("Writes a FLR file using JSefa.")
 public class JSefaFlrWriter extends JSefaWriter {
     @Inject
     @BatchProperty
+    @Documentation("Which ref or implementation to use to filter lines")
     private String lineFilter;
 
     @Inject
     @BatchProperty
+    @Documentation("low level configuration implementation")
     private String lowLevelConfiguration;
 
     @Inject
     @BatchProperty
+    @Documentation("if not using a custom line filter how many lines to filter")
     private String lineFilterLimit;
 
     @Inject
     @BatchProperty
+    @Documentation("record delimiter")
     private String specialRecordDelimiter;
 
     @Inject
     @BatchProperty
+    @Documentation("EOL")
     private String lineBreak;
 
     @Inject
     @BatchProperty
+    @Documentation("pad character")
     private String defaultPadCharacter;
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaReader.java
----------------------------------------------------------------------
diff --git a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaReader.java b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaReader.java
index 544bfa9..05cb3a6 100644
--- a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaReader.java
+++ b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaReader.java
@@ -16,8 +16,9 @@
  */
 package org.apache.batchee.jsefa;
 
-import org.apache.batchee.extras.transaction.CountedReader;
 import net.sf.jsefa.Deserializer;
+import org.apache.batchee.doc.api.Documentation;
+import org.apache.batchee.extras.transaction.CountedReader;
 
 import javax.batch.api.BatchProperty;
 import javax.inject.Inject;
@@ -27,30 +28,37 @@ import java.io.Serializable;
 public abstract class JSefaReader extends CountedReader {
     @Inject
     @BatchProperty
+    @Documentation("object types to use")
     protected String objectTypes;
 
     @Inject
     @BatchProperty
+    @Documentation("validation mode (AUTO, CALLBACK, NONE)")
     protected String validationMode;
 
     @Inject
     @BatchProperty
+    @Documentation("object accessor provider implementation")
     protected String objectAccessorProvider;
 
     @Inject
     @BatchProperty
+    @Documentation("validation provider implementation")
     protected String validationProvider;
 
     @Inject
     @BatchProperty
+    @Documentation("simple type provider implementation")
     protected String simpleTypeProvider;
 
     @Inject
     @BatchProperty
+    @Documentation("type mapping registry to use")
     protected String typeMappingRegistry;
 
     @Inject
     @BatchProperty
+    @Documentation("file to read")
     protected String file;
 
     protected Deserializer deserializer;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaWriter.java
----------------------------------------------------------------------
diff --git a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaWriter.java b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaWriter.java
index 9ac4e22..c53040b 100644
--- a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaWriter.java
+++ b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaWriter.java
@@ -16,8 +16,9 @@
  */
 package org.apache.batchee.jsefa;
 
-import org.apache.batchee.extras.transaction.TransactionalWriter;
 import net.sf.jsefa.Serializer;
+import org.apache.batchee.doc.api.Documentation;
+import org.apache.batchee.extras.transaction.TransactionalWriter;
 
 import javax.batch.api.BatchProperty;
 import javax.batch.api.chunk.ItemWriter;
@@ -30,34 +31,42 @@ import java.util.List;
 public abstract class JSefaWriter implements ItemWriter {
     @Inject
     @BatchProperty
+    @Documentation("object types to use")
     protected String objectTypes;
 
     @Inject
     @BatchProperty
+    @Documentation("validation mode (AUTO, CALLBACK, NONE)")
     protected String validationMode;
 
     @Inject
     @BatchProperty
+    @Documentation("object accessor provider implementation")
     protected String objectAccessorProvider;
 
     @Inject
     @BatchProperty
+    @Documentation("validation provider implementation")
     protected String validationProvider;
 
     @Inject
     @BatchProperty
+    @Documentation("simple type provider implementation")
     protected String simpleTypeProvider;
 
     @Inject
     @BatchProperty
+    @Documentation("type mapping registry to use")
     protected String typeMappingRegistry;
 
     @Inject
     @BatchProperty
+    @Documentation("file to write")
     protected String file;
 
     @Inject
     @BatchProperty
+    @Documentation("output file encoding")
     protected String encoding;
 
     protected Serializer serializer;

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaXmlReader.java
----------------------------------------------------------------------
diff --git a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaXmlReader.java b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaXmlReader.java
index 16fed53..26df843 100644
--- a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaXmlReader.java
+++ b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaXmlReader.java
@@ -18,33 +18,41 @@ package org.apache.batchee.jsefa;
 
 import net.sf.jsefa.Deserializer;
 import net.sf.jsefa.xml.XmlIOFactory;
+import org.apache.batchee.doc.api.Documentation;
 
 import javax.batch.api.BatchProperty;
 import javax.inject.Inject;
 
+@Documentation("Reads a XML file using JSefa.")
 public class JSefaXmlReader extends JSefaReader {
     @Inject
     @BatchProperty
+    @Documentation("low level configuration implementation")
     private String lowLevelConfiguration;
 
     @Inject
     @BatchProperty
+    @Documentation("EOL")
     private String lineBreak;
 
     @Inject
     @BatchProperty
+    @Documentation("registry name for data type")
     private String dataTypeDefaultNameRegistry;
 
     @Inject
     @BatchProperty
+    @Documentation("indentation")
     private String lineIndentation;
 
     @Inject
     @BatchProperty
+    @Documentation("namespace manager to use")
     private String namespaceManager;
 
     @Inject
     @BatchProperty
+    @Documentation("data type attribute name")
     private String dataTypeAttributeName;
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaXmlWriter.java
----------------------------------------------------------------------
diff --git a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaXmlWriter.java b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaXmlWriter.java
index 928daaa..6bee49d 100644
--- a/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaXmlWriter.java
+++ b/extensions/jsefa/src/main/java/org/apache/batchee/jsefa/JSefaXmlWriter.java
@@ -18,33 +18,41 @@ package org.apache.batchee.jsefa;
 
 import net.sf.jsefa.Serializer;
 import net.sf.jsefa.xml.XmlIOFactory;
+import org.apache.batchee.doc.api.Documentation;
 
 import javax.batch.api.BatchProperty;
 import javax.inject.Inject;
 
+@Documentation("Reads a XML file using JSefa.")
 public class JSefaXmlWriter extends JSefaWriter {
     @Inject
     @BatchProperty
+    @Documentation("low level configuration implementation")
     private String lowLevelConfiguration;
 
     @Inject
     @BatchProperty
+    @Documentation("EOL")
     private String lineBreak;
 
     @Inject
     @BatchProperty
+    @Documentation("Registry name for data type")
     private String dataTypeDefaultNameRegistry;
 
     @Inject
     @BatchProperty
+    @Documentation("indentation")
     private String lineIndentation;
 
     @Inject
     @BatchProperty
+    @Documentation("namespace manager to use")
     private String namespaceManager;
 
     @Inject
     @BatchProperty
+    @Documentation("data type attribute name")
     private String dataTypeAttributeName;
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/modelmapper/src/main/java/org/apache/batchee/modelmapper/ModelMapperItemProcessor.java
----------------------------------------------------------------------
diff --git a/extensions/modelmapper/src/main/java/org/apache/batchee/modelmapper/ModelMapperItemProcessor.java b/extensions/modelmapper/src/main/java/org/apache/batchee/modelmapper/ModelMapperItemProcessor.java
index d52cace..464d8b5 100644
--- a/extensions/modelmapper/src/main/java/org/apache/batchee/modelmapper/ModelMapperItemProcessor.java
+++ b/extensions/modelmapper/src/main/java/org/apache/batchee/modelmapper/ModelMapperItemProcessor.java
@@ -16,25 +16,29 @@
  */
 package org.apache.batchee.modelmapper;
 
+import org.apache.batchee.doc.api.Documentation;
 import org.modelmapper.ModelMapper;
 import org.modelmapper.config.Configuration;
 import org.modelmapper.convention.MatchingStrategies;
 import org.modelmapper.spi.MatchingStrategy;
 
-import java.util.Locale;
 import javax.batch.api.BatchProperty;
 import javax.batch.api.chunk.ItemProcessor;
 import javax.inject.Inject;
+import java.util.Locale;
 
+@Documentation("uses model mapper to process the item")
 public class ModelMapperItemProcessor implements ItemProcessor {
     private volatile ModelMapper mapper = null;
 
     @Inject
     @BatchProperty
+    @Documentation("matching strategy to use (LOOSE, STANDARD, STRICT or custom implementation)")
     private String matchingStrategy;
 
     @Inject
     @BatchProperty
+    @Documentation("target type")
     private String destinationType;
     private volatile Class<?> destinationTypeClass = null;
 

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/extensions/pom.xml
----------------------------------------------------------------------
diff --git a/extensions/pom.xml b/extensions/pom.xml
index ade854e..5a93fd2 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -51,6 +51,12 @@
             <groupId>org.apache.geronimo.specs</groupId>
             <artifactId>geronimo-atinject_1.0_spec</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.batchee</groupId>
+            <artifactId>batchee-doc-api</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
 
         <dependency>
             <groupId>org.testng</groupId>
@@ -66,8 +72,61 @@
             <groupId>org.apache.derby</groupId>
             <artifactId>derby</artifactId>
         </dependency>
+
+        <dependency> <!-- just there for mvn-exec and deps ordering -->
+            <groupId>org.apache.batchee</groupId>
+            <artifactId>batchee-maven-plugin</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.batchee</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
     </dependencies>
 
+    <build>
+        <plugins>
+            <plugin> <!-- would be cool to reuse our plugin but doesnt work in the same build -->
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <version>1.4.0</version>
+                <executions>
+                    <execution>
+                        <phase>pre-site</phase>
+                        <goals>
+                            <goal>java</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <mainClass>org.apache.batchee.tools.maven.doc.ComponentDocumentationGenerator</mainClass>
+                    <includePluginDependencies>true</includePluginDependencies>
+                    <arguments>
+                        <argument>${project.build.outputDirectory}</argument>
+                        <argument>${project.parent.parent.basedir}/src/site/markdown/batchee-site-generated/${project.artifactId}.md</argument>
+                        <argument>md</argument>
+                    </arguments>
+                </configuration>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.apache.batchee</groupId>
+                        <artifactId>batchee-maven-plugin</artifactId>
+                        <version>${project.version}</version>
+                        <exclusions>
+                            <exclusion>
+                                <groupId>org.apache.batchee</groupId>
+                                <artifactId>*</artifactId>
+                            </exclusion>
+                        </exclusions>
+                    </dependency>
+                </dependencies>
+            </plugin>
+        </plugins>
+    </build>
+
     <profiles>
         <profile>
             <id>cdi-1.0</id>

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/tools/doc-api/src/main/java/org/apache/batchee/doc/api/Configuration.java
----------------------------------------------------------------------
diff --git a/tools/doc-api/src/main/java/org/apache/batchee/doc/api/Configuration.java b/tools/doc-api/src/main/java/org/apache/batchee/doc/api/Configuration.java
deleted file mode 100644
index 2de07f8..0000000
--- a/tools/doc-api/src/main/java/org/apache/batchee/doc/api/Configuration.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.batchee.doc.api;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-@Retention(CLASS)
-@Target({ FIELD, METHOD, PARAMETER, TYPE })
-public @interface Configuration {
-    String value();
-}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/95e199aa/tools/doc-api/src/main/java/org/apache/batchee/doc/api/Documentation.java
----------------------------------------------------------------------
diff --git a/tools/doc-api/src/main/java/org/apache/batchee/doc/api/Documentation.java b/tools/doc-api/src/main/java/org/apache/batchee/doc/api/Documentation.java
new file mode 100644
index 0000000..c5ea36d
--- /dev/null
+++ b/tools/doc-api/src/main/java/org/apache/batchee/doc/api/Documentation.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.batchee.doc.api;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+@Retention(CLASS)
+@Target({ FIELD, METHOD, PARAMETER, TYPE })
+public @interface Documentation {
+    String value();
+}