axel framework

The framework builds web pages using instructions, commonly known as actions, placed inside each page.


Details on how to use each action are shown in the tutorials. You'll also learn how to build and deploy web applications. How to connect to backend and external resources such as databases and json feeds.

To get started you need some knowledge on command line such as windows cmd, using a browser and a basic understanding of html.


How to build an application with Axel and Springboot

You need some familiarity with

  • Command Line
  • Java
  • Springboot
  • Gradle

  • These instructions show how to configure Axel to run with Springboot. The steps include

  • How to setup a gradle build script
  • Dependent libraries required to run Axel and Springboot
  • Building a runable jar file
  • Running Springboot and accessing Axel using localhost

  • This diagram shows Web Browsers communicating with a Web Server running Springboot. Springboot is configured to pass http requests to Axel through the Tomcat engine included with the build.

    Action Schema


    These are the files that we use to build the application

        axel-springboot -> build.gradle
                        -> src -> main -> java -> axel -> AxelApplication.java
                        -> src -> main -> resources -> application.yml
                                                    -> log4j.properties
                                                    -> spring-axel.xml
                

    Installation Steps

    1. Download this zip file and extract to your local disk drive in a folder of your choice axel-springboot.zip

    2. Install Java 8 or highter if not already installed Java Download Page

    3. Install Gradle if not already installed Gradle Download Page

    Build Steps

    1. Open a command / terminal window and cd to the axel-springboot folder

    2. Type gradle clean build to build the project - When the build is complete the axel-springboot.jar is located in the build/libs folder

    3. Type java -jar build\libs\axel-springboot.jar to run the springboot application

    4. Open your browser and type localhost in the address bar - You should see an error in the browser with a message "file not found index.html"

    5. Create a file named index.html and add "Hello World !!! from axel"

    6. Refresh your browser - You should see "Hello World !!! from axel" in your browser window

    Next Steps - Hints

    Axel is now working with Springboot. You can add axel actions to your pages and see the results by refreshing your browser.

    If you create a batch / script file you can add this to your path and then run axel-springboot from any location. Makes if easy to build multiple web projects.
    java -jar c:\your\folder\axel-springboot.jar

    You can change the default port of 80 to any port number by adding -Dserver.port=port.number to your batch/script file.
    java -jar -Dserver.port=8080 c:\your\folder\axel-springboot.jar


    build.gradle

    The build.gradle used to buold the axel-bootstrap.jar

    buildscript {
        repositories {
    		mavenCentral()
    	}
    	dependencies {
    		classpath("org.springframework.boot:spring-boot-gradle-plugin:2.2.9.RELEASE")
    	}
    }
    
    plugins {
    	id "org.springframework.boot" version "2.2.9.RELEASE"
    	id 'java'
    }
    apply plugin: 'io.spring.dependency-management'
    
    repositories {
    	mavenLocal()
    	mavenCentral()
    }
    
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
    
    
    jar {
    	println("axelVersion:$axelVersion")
    	from sourceSets.main.allSource
    	manifest {
    		println("manifest:axelVersion:$axelVersion")
    		attributes (
    			"Main-Class": "axel.AxelApplication",
    			"Axel-Version": "$axelVersion"
    		)
    	}
    }
    
    task customFatJar(type: Jar) {
    	println("customFatJar:axelVersion:$axelVersion")
    	manifest {
    		println("customFatJar:manifest:axelVersion:$axelVersion")
    		attributes (
    			"Main-Class": "axel.AxelApplication",
    			"Axel-Version": "$axelVersion"
    		)
    	}
    	baseName = 'axel-run'
    	from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    	with jar
    	manifest {
    		println("customFatJar2:manifest:axelVersion:$axelVersion")
    		attributes (
    			"Main-Class": "axel.AxelApplication",
    			"Axel-Version": "$axelVersion"
    		)
    	}
    }
    
    configurations.all {
    	exclude group:'org.springframework.boot', module:'spring-boot-starter-logging'
    	exclude group:'org.apache.tomcat', module:'servlet-api'
    }
    
    test {
        useJUnitPlatform()
    }
    
    dependencies {
    	compile 'org.xmlactions:axelframework:3.1.10'
    	compile 'com.google.code.gson:gson:2.8.6'
    	compile 'org.json:json:20140107'
    	compile 'commons-lang:commons-lang:2.6'
    	compile 'commons-beanutils:commons-beanutils:1.8.3'
    	compile 'commons-configuration:commons-configuration:1.9'
    	compile 'commons-io:commons-io:1.4'
    	compile 'commons-fileupload:commons-fileupload:1.3.3'
    	compile 'commons-digester:commons-digester:2.1'
    	compile 'rhino:js:1.7R2'
    	compile 'dom4j:dom4j:1.6.1'
    	compile 'bsf:bsf:2.4.0'
    	compile 'javax.mail:mail:1.4.7'	
    	compile 'jasperreports:jasperreports:3.5.3'
    	compile 'org.springframework.boot:spring-boot-starter-web'
    }

    AxelApplication.java

    How we start spring boot and add listeners for servicing requests.

    package axel;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.io.IOUtils;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.servlet.ServletRegistrationBean;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.ImportResource;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.HandlerMapping;
    import org.xmlactions.web.PagerServlet;
    import org.xmlactions.web.conceal.HttpPager;
    
    @SpringBootApplication
    @Configuration
    @ImportResource({"classpath:spring-axel.xml"})
    @Controller
    public class AxelApplication {
    
    	private static ApplicationContext applicationContext;
    	
    	public static void main(String[] args) {
    		applicationContext  = SpringApplication.run(AxelApplication.class, args);
    		
    		if(args.length > 0) {
    			HttpPager.setRealPath(args[0]);
    		} else {
    			HttpPager.setRealPath(".");
    		}
    	}
    	
    	public static ApplicationContext getApplicationContext() {
    		return applicationContext;
    	}
    	
    	/**
    	 * This services all browser page requests that match the Url Mapping "*.html","*.json", "*.csv", "*.js", "*.css".  Add
    	 * or remove these mappings as you need.
    	 *
    	 * It also tells the bean to process all axel action requests that are defined with "axel", as an example
    	 * <axel:echo>Hello World!!!</axel:echo>
    	 * 
    	 * @return A ServletRegistrationBean
    	 */
    	@Bean
    	public ServletRegistrationBean axelServlet() {
    		ServletRegistrationBean servRegBean = new ServletRegistrationBean<>();
    		HttpPager httpPager = new HttpPager();
    		servRegBean.setServlet(new PagerServlet(httpPager));
    		servRegBean.addInitParameter("pager.namespace", "axel");
    		servRegBean.addUrlMappings("*.html","*.json", "*.csv", "*.js", "*.css"); //  "*.png", "*.jpg");
    		servRegBean.setLoadOnStartup(1);
    		return servRegBean;
    	}
    	
    	/**
    	 * This services all browser page requests that do not match the axelServlet detailed above.
    	 *
    	 * It basically loads and returns the content of file by inserting the content into the HttpResponse 
    	 */
    	@RequestMapping("**")
    	public void processAllOthers(HttpServletRequest request, HttpServletResponse response) throws IOException {
    		String pf = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
    		if (StringUtils.isNotEmpty(pf) && (pf.startsWith("/"))) {
    			pf = pf.substring(1);
    		}
    		if (StringUtils.isEmpty(pf)) {
    			pf = "index.html";	// set default to "index.html"
    		}
    		InputStream in = new FileInputStream(pf);
    		IOUtils.copy(in, response.getOutputStream());
    	}
    	
    	
    	
    }

    application.yml

    The yaml definition used for deployment - note the logging config is contained in the log4j.properties

    spring:
      application:
        name: axel-springboot
      profiles:
        active: dev
    server:
      port: 80
      servlet:
        context-path: /
      contextPath: /
    logging:
      pattern:
        console: "[${serverName}:${spring.application.name}] %date{HH:mm:ss} %-6level %-10([%thread]) %logger{1}.%method:%line %message%n"
        file:    "[${serverName}:${spring.application.name}] %date{HH:mm:ss} %-6level %-10([%thread]) %logger{1}.%method:%line %message%n"
      file: /var/log/ts/api-${spring.application.name}.log
      level:
        org.apache: WARN
        org.springframework: WARN
        org.hibernate: WARN
    
    

    log4j.properties

    Used to set the logging level and output file

    log4j.rootLogger=DEBUG, stdout, R
    
    # Exclusion Classes
    log4j.logger.org.springframework=WARN
    log4j.logger.org.apache.commons=WARN
    log4j.logger.org.hibernate=WARN
    log4j.logger.org.xmlactions=WARN
    log4j.logger.org.xmlactions.mapping=WARN
    
    #log4j.logger.org.xmlactions.action.actions.BaseAction=INFO
    #log4j.logger.org.xmlactions.action.actions.SetupBeanFromXML=INFO
    log4j.logger.org.srg.spriongframework.boot=WARN
    
    # Standard output logging
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%d{MMM:dd:HH:mm:ss,SSS}:[%t]:(%C{1}.%M:%L):%-5p:%c{1}:%m%n
    #log4j.appender.stdout.layout.ConversionPattern=%d{MMM:dd:HH:mm:ss,SSS}:[%t]:%-5p:%c{1}:%m%n
    
    # Rolling file logging
    log4j.appender.R=org.apache.log4j.RollingFileAppender
    log4j.appender.R.File=axel-run.log
    log4j.appender.R.MaxFileSize=5MB
    log4j.appender.R.MaxBackupIndex=3
    log4j.appender.R.layout=org.apache.log4j.PatternLayout
    log4j.appender.R.layout.ConversionPattern=%d{MMM:dd:HH:mm:ss,SSS}:[%t]:(%C{1}.%M:%L):%-5p:%c{1}:%m%n
    #log4j.appender.R.layout.ConversionPattern=%d{MMM:dd:HH:mm:ss,SSS}:[%t]:%-5p:%c{1}:%m%n
    
    

    spring-axel.xml

    The spring xml configuration file

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:util="http://www.springframework.org/schema/util"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:jee="http://www.springframework.org/schema/jee"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
        <!-- M.M. All execution contexts are derived from this. -->
        <bean id="pager.execContext" name="pager.execContext" class="org.xmlactions.pager.context.SessionExecContext" scope="session">
            <qualifier value="pager.execContext"/>
            <constructor-arg>
                <!-- "actionMaps" -->
                <list>
                    <!-- These are included with the axelframwork.jar -->
                    <util:properties location="classpath:config/pager/actions.properties" />
                </list>
            </constructor-arg>
            <!-- "localMaps" additional configuration properties may be added here -->
            <!-- 
            <constructor-arg>
                <list>
                    <util:properties location="classpath:config/project/web.properties" />
                </list>
            </constructor-arg>
             -->
        </bean>
    </beans>