Help

Built with Seam

You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.



Forge

A core framework for rapid-application development in a standards-based environment. Plugins / incremental project enhancement for Java EE, and more.


Note: This project requires Maven 3 and Java 6 - ( Get Involved! )

Maintainers and contributors

Name Organization Role Hometown (Time zone)
Lincoln Baxter III JBoss, by Red Hat Project Lead Charlotte, NC, USA (UTC-05)
Mike Brock JBoss, by Red Hat Scripting & Errai Integration Lead Toronto, ON (UTC-05)
Koen Aers JBoss, by Red Hat JBoss Tools Integation Lead Antwerp, BE (UTC+01)

Get Involved

Got an idea? Want to get your feet wet? Do some Forgestorming: http://bit.ly/forgestorm - def: forgestorm (v.) [for-ge-st-orm] - The act of brainstorming when applied to Forge watch mayweather vs ortiz online

  1. Check out the code:
    git clone git://github.com/forge/core.git forge
  2. 'cd' into the project directory:
    cd forge
  3. Build the code:
    mvn install
  4. 'cd' into the dist/ directory:
    cd dist
  5. Execute Forge:
    mvn exec:java
Note: Maven 3 and Java 6 are required to build this project.

Contribute

  1. Fork the repository on GitHub: http://github.com/forge/core and clone it to your local PC
    git clone git@github.com:{your user}/{your forge repo}.git
  2. If you haven't done so already, sign the JBoss CLA: https://cla.jboss.org/
  3. Create an issue in the issue tracker: https://issues.jboss.org/browse/SEAMFORGE
  4. Create a branch for your issue, where XX is the issue number:
    git branch SEAMFORGE-XX
    git checkout SEAMFORGE-XX
  5. Make your changes and write unit tests for them.
  6. Commit your changes
    git add -A
    git commit -m "Implemented SEAMFORGE-XX"
  7. If you made multiple commits, use rebase to squash them into a single commit, where 5 is the number of commits to rebase:
    git rebase -i HEAD~5
    Change 'pick' to 's' for each commit you wish to squash upwards. (If you do not change a line, it will not be modified.)
      1 pick ade2b1a Implemented SEAMFORGE-XX
      2 s c3ae0a2 almost done
      3 s c863bfb did more work
      4 s af793ae Started working on SEAMFORGE-XX
      5 pick 368bbb9 RepositoryLookup falls back to Central by default
    
    Once you are done, your commits should look like this:
      1 ade2b1a Implemented SEAMFORGE-XX
      2 368bbb9 RepositoryLookup falls back to Central by default
    
  8. Push to your branch:
    git push origin SEAMFORGE-XX
  9. Submit a pull request from your branch. The pull request should include one single commit changing all of your changes. If you have more than one commit, then you did not rebase correctly.
    http://github.com/{your user}/{your forge repo}/tree/{SEAMFORGE-XX}
  10. Link the pull request to the JIRA via Workflow -> Link Pull Request

Sync/Update your Repository

1 This step only needs to occur once:

git remote add upstream git://github.com/forge/core.git
2 Pull the changes from upstream and merge them into your current branch:
git pull upstream master

Debug Forge

Once you have checked out and built the sources, you can debug Forge by taking the following steps:

  1. cd forge/dist/
  2. mvnDebug exec:java
  3. Link to your eclipse debugger: http://docs.codehaus.org/display/MAVENUSER/Dealing+with+Eclipse-based+IDE

Release plan

(status: draft) - This plan is still being defined.

Version Time frame Focus
1.0.0.Beta2 or 1.0.0.CR1 (In Progress) ~ September
  • Provide navigation for CRUD
  • Enhance scaffolding
  • Enhance plugin installation/removal
1.0.0.Beta1 (In Progress) ~ August
  • Plugin repository hosted and searchable
  • Use JBoss Modules to isolate plugins
  • Deploy to AS7
  • Deploy to OpenShift
  • Provide navigation for CRUD
1.0.0.Alpha4 "Birthday" Released June 9, 2011
  • Scaffolding framework broken down and de-coupled
  • Provide basic functional CRUD
  • Maven Project Model API stabilized
  • Built in Facets API stabilized
  • Enabled removal of facets
1.0.0.Alpha3 "Angry Kittens" Released ~ March 30th
  • Plugin distribution framework implemented
  • JPA configuration implemented
  • CDI configuration implemented
  • JSF configuration implemented
1.0.0.Alpha2 "Angry Kitten" (Released) ~ February
  • JBoss Tools integration prototyped
  • Dependency manipulation plugins prototyped
  • Java manipulation plugins prototyped
  • XML Facelet View file manipulation prototyped
  • More robust and customizable scaffolding functionality
1.0.0.Alpha1 "Angry Kitten" Released ~ November
  • Java Manipulation API Stabilized
  • Plugin Framework API Stabilized
  • Continued integration and feedback for refactoring
~ October
  • Additional addons prototyped (GWT, JSF, JPA ... etc)
  • Plugin framework feedback incorporated and refactored
~ September
  • Plugin Framework Events initial testing and application begins. (in progress )
  • First set of plug-ins for project bootstrapping
  • Tooling feedback incporated and refactored
~ August
  • Basic Java Manipulation API
  • Maven Integration
  • Basic CLI Runner or Prototype Shell
  • Initial set of Plugin Framework Events (Based on CDI)
  • Tooling team consulted for IDE integration in JBoss Tools

Simplicity at work

Design notes

(To be continued as more ideas roll in.)

Major Facets

  • Continuous Project Enhancement
  • Rapid Application Developemnt
  • Shell-style interaction while enabling a strong tooling suite
  • Single-command style interaction via native command line
  • Plugin-based: standardized around a core set of manipulation APIs for Java sources, XML, Maven POMs, Java Archives (ShrinkWrap)
  • Internal architecture founded on CDI/Weld
  • Technology agnostic, may be used to create application frameworks for any technology or language.
  • Support for internationalization and localization (i18n and l10n)
  • Support for maven artifact discovery and version selection: (http://arquillian.pastebin.com/nE5NbmyH)
  • Incremental database reverse-engineering w/Hibernate Tools

Potential Plugins / Brainstorming

  • Set project.build.finalName of project (sets name of generated artifact)
  • Create a blank JSF view template
  • Add a taglib namespace to a JSF view template
  • Setup Solder logging annotation processor
  • Set an initial property on bean in seam-beans.xml (Seam Config)
  • Maven repository configurer (updates settings.xml or pom.xml with necessary repositories for dependencies)
  • Scaffolding framework
  • Automatic test stub generation
  • Generate/Run/Deploy webapp
  • Generate executable JAR/WAR that can leverage JBoss embedded to provide a simplified deliverable - e.g. Generating a webapp that can be run as a Java app like Grails.
  • Seam2 to Seam3 migration plugin/toolkit.
  • ability to reference project settings through EL in Default @Option params:
    @Option(default="org.${project.name}") String defaultPackage
  • File monitoring with JNotify
  • XML Formatting w/JTidy (XMLPrettyPrinter in Hibernate Tools Core)
  • Source file header maintainance plugin (find and replace with consistent copyright.)
  • Manpage-like JavaDoc plugin javadoc javax.servlet.Servlet
  • Mark locations: cd src/main/java...mark java... show marks (marks) ... cd/go java

Maven plugin executable:

For faster installation & bootstrap:

mvn org.jboss.seam:seamforge

would result in downloading the forge dist, executing it.

Creating a barebones Maven Project (Functional)

[no project] /home/lb3/Desktop $ new-project
[The name of the new project (java.lang.String)]: example
Use [/home/lb3/Desktop/example] as project directory? [Y/n] y
Please enter your base package [e.g: "com.example.project"] com.example
***SUCCESS*** Created project [example] in new working directory [/home/lb3/Desktop/example]
[example] /home/lb3/Desktop/example $

Plugin API (Functional)

Maven Artifact:

         <dependency>
            <groupId>org.jboss.seam.forge</groupId>
            <artifactId>forge-shell-api</artifactId>
            <version>${project.version}</version>
         </dependency>

example of how the plugin would be invoked from the shell: displays help information about the system, plugins, and commands

[no project] /home/lb3/Desktop $ help
/**
 * @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
 */
@Named("help")
@Help("Displays help text for specified plugins & commands.")
public class HelpPlugin implements Plugin
{
   @Inject
   PluginRegistry registry;

   @Inject
   Shell shell;

   @DefaultCommand(help = "Get help about specific commands")
   public void help(@Option final String... commands)
   {
      if ((commands == null) || (commands.length == 0))
      {
         shell.println("Welcome to Encore!");
      }
      else
      {
         shell.println("[" + commands[0] + "] " + registry.getPlugins().get(commands[0]).getHelp());
      }
   }
}

Simplified Source Code Manipulation (Functional)

Maven Artifact:

         <dependency>
            <groupId>org.jboss.seam.forge</groupId>
            <artifactId>forge-parser-java</artifactId>
            <version>${project.version}</version>
         </dependency>

Needs code formatting from Eclipse JDT.

Example usage via a JUnit Test:

public class JavaClassTest
{
   private InputStream stream;
   private JavaClass javaClass;

   @Before
   public void reset()
   {
      stream = JavaClassTest.class
               .getResourceAsStream("/org/jboss/encore/grammar/java/MockClassFile.java");
      javaClass = new JavaClass(stream);
   }

   @Test
   public void testParse() throws Exception
   {
      List<Import> imports = javaClass.getImports();
      assertEquals(URL.class.getName(), imports.get(0).getName());
   }

   @Test
   public void testAddMethodFromString() throws Exception
   {
      javaClass.addMethod("public URL rewriteURL(String pattern, String replacement) { return null; }")
               .setPackagePrivate().applyChanges();
      List<Method> methods = javaClass.getMethods();
      assertEquals(3, methods.size());
      assertEquals("URL", methods.get(2).getReturnType());
      assertEquals("rewriteURL", methods.get(2).getName());

      String body = methods.get(2).getBody();
      assertEquals("return null;".replaceAll("\\s+", ""),
                     body.replaceAll("\\s+", ""));
   }

   @Test
   public void testRemoveMethod() throws Exception
   {
      // TODO Removing methods needs to work
      List<Method> methods = javaClass.getMethods();
      javaClass.removeMethod(methods.get(0)).applyChanges();
      methods = javaClass.getMethods();
      assertEquals(1, methods.size());
   }

Test Harness API (Functional)

Maven Dependency:

         <dependency>
            <groupId>org.jboss.seam.forge</groupId>
            <artifactId>forge-test-harness</artifactId>
            <version>${project.version}</version>
         </dependency>

Example usage: (Any shell operation can be performed, using the default shell implementation. A new base-project is created, and the shell is re-initialized for each test method invocation.)

@RunWith(Arquillian.class)
public class ShellImplTest extends AbstractShellTest
{
   @Test
   public void testPromptBoolean() throws Exception
   {
      queueInputLines("y");
      assertTrue(getShell().promptBoolean("Would you like cake?"));

      queueInputLines("yes");
      assertTrue(getShell().promptBoolean("Would you like cake?"));

      queueInputLines("n");
      assertFalse(getShell().promptBoolean("Would you like cake?"));

      queueInputLines("no");
      assertFalse(getShell().promptBoolean("Would you like cake?"));
   }
}

Core Shell Features (under development, prototyped)

  • --pretend : causes all file modifications to be performed in a parallel directory structure, after which creating a Diff to be displayed to the user / consumed by tooling; any parallel files created are to be removed after execution.
  • tab-completion : pressing TAB will complete the current partially typed command or option.
  • tab-completion(contextual) : pressing TAB will trigger command/option auto-completion, where the next required option (sorted alphabetically) is appended to the prompt input. If a partially typed command/option is ambiguous, or if no more required options are present, display a list of remaining non-required options. This feature must be context sensitive to the current list of commands/arguments that have already been typed on the console.

Customizable configuration (proposed)

.forge

file:

plugin.scaffold.domainPackage="~.domain2.entities"
plugin.scaffold.autoUpdate=false

plugin.scaffold.viewPath="~/faces/views/"

Plugin ordering and conflicts (under development, prototyped)

There will certainly be situations where some plugins must operate before others. A CDI event bus will be in place to ensure ordering of said events, and allowing for propagation of file changes throughout the plugin listeners, in a manner that prevents cyclic operations.

Tooling interegration options (proposed)

  • Embedded JMS Queue (HornetQ) for transfer of events between IDE and Shell
  • Simple socket communication
  • File polling (append updates to a flat file w/timestamps & metadata)

Templating and Scaffolding Framework (proposed)

Lightweight and powerful templating http://www.pastie.org/1146629
http://www.pastie.org/1146678