Approximately 9 months after we released appserver version 1.0.0 and 10.000+ downloads later, we’re proud to announce the GA release of our next major point release of appserver. Version 1.1.0 “Iron Knight”. This new version contains many bug fixes and a number of new and very interesting features.

The following list is a short overview of the great additions you will get with version 1.1.0 “Iron Knight”:

  • Powered with PHP 5.6.x
  • Runlevels
  • Management Console (Terminal) - Currently Experimental
  • A CRON system
  • Multiple SSL Certificates possible per IP
  • A Proxy Module
  • An AutoIndex Module
  • A Headers Module
  • New Application Configuration
  • Complete Doctrine Integration (@PersistenceUnit annotation)
  • Lifecycle Callbacks for SFSB (@PostDetach, @PreAttach)

You can find a detailed overview of all the fixed bugs and closed issues on our Github Releases page.

Platform

Since appserver is a full stack platform, we define the PHP runtime version and the main daemon, which starts all other services, servers and finally the applications. The following updates and features are part of 1.1.0 “Iron Knight” platform.

PHP 5.6.x

Version 1.1.x is, as defined in issue #683, now based on PHP 5.6.x and contains many security patches and performance improvements, as well as a whole bunch of new PHP functionality.

Runlevels

The latest version of appserver.io also comes with a completely refactored and improved boostrap process, which is now separated in seven modes of operation, called Runlevels. Below is a list of the different levels:

ID Name Description
0 Shutdown Stop the Application Server
1 Administration Start the Base System
2 Daemon Start the Core Daemons
3 Networking Start the Containers
4 Secure Secure the Application Server
5 Full Initialize and Start the Applications
6 Restart Restart the Application Server

When appserver.io is started, by invoking service appserver start on a Linux system’s console, Runlevel 5 will be executed. But, prior to this initial server start, all previous Runlevels are actually synchronously executed, whereas

  • runlevel 1 loads the system configuration and start’s the base system
  • runlevel 2 start’s the core daemons e. g. the telnet console
  • runlevel 3 start’s containers and the services e. g. the HTTP(S) server
  • runlevel 4 secures the servers by switching to the configured group and user
  • runlevel 5 finally bootstraps and start’s the deployed applications

This new boostrap process now uses events, which allows developers, who want to create their own startup functionality, to hook into the runlevel processes to execute their code within the required runlevel. These events can be easily configured through the etc/appserver/conf.d/bootstrap.xml file. Additionally, there are separate configuration files for the watcher daemon etc/appserver/conf.d/boostrap-watcher.xml and the setup command etc/appserver/conf.d/bootstrap-command.xml.

Management Console (Experimental)

You may be asking yourself, is it possible to switch between the runlevels? Yes, it is! With version 1.1.0, the OS specific init scripts only allowed you to start/stop or restart appserver.io. Now, the Management Console enables developers or admins to login to an instance and allows them to execute various commands, like switching between the runlevels.

This feature had been planned in issue #763 and specifies a Management Console that allows the execution of commands on an internal commandline.

The Management Console is currently experimental and in a pre-alpha stage. This means switching between the runlevels using the init command, along with the exit command, are the only functionality available currently with version 1.1.0. The Management Console supports different protocols, however only the Telnet based implementation is operational. We plan to integrate an SSH console in one of the future releases. We will also be extending the functionality. The list below shows a few examples of some of the up and coming commands, which will be made available over the Management Console:

  • su: Switching the user
  • top: Overview all threads with required memory and CPU time
  • status: Textual overview about the server status
  • service: Start and stop container, servers and applications

The Management Console can be configured through the main configuration file etc/appserver/appserver.xml. By default, the Telnet based implementation is activated

...
<consoles>
    <console
        name="telnet"
        type="AppserverIo\Appserver\Core\Consoles\Telnet"
        factory="AppserverIo\Appserver\Core\Consoles\TelnetFactory">
        <params>
            <param name="address" type="string">127.0.0.1</param>
            <param name="port" type="integer">9023</param>
        </params>
    </console>
</consoles>
...

In the configuration above, the Management Console will listen to local port 9023. This can be deactivated or customized, as the Management Console is currently for testing purposes only.

CRON

The new CRON functionality can replace the regular system CRON. It allows admins to configure CRON jobs globally. The main advantage of the appserver CRON is to allow developers to deliver their CRON job configuration along with their appserver applications. The global CRON job configuration can be found and modified under etc/appserver/conf.d/cron.xml, whereas the application specific CRON configuration files will be located under META-INF/cron.xml.

Below is a simple example showing a CRON configuration, which writes the actual PHP version to the var/log/php_errors.log:

<?xml version="1.0" encoding="UTF-8"?>
<cron xmlns="http://www.appserver.io/appserver">
    <jobs>
        <job name="render-php-version">
            <schedule>0 * * * * *</schedule>
            <execute directory="/opt/appserver" script="bin/php">
                <args>
                    <arg type="string">-v</arg>
                </args>
            </execute>
        </job>
    </jobs>
</cron>

You can find more information about CRON job configuration in our configuration documentation.

Webserver improvements

In addition to the improvements made to the general appserver platform, we’ve also invested a good bit of work to offer a fully featured HTTP 1.1 compliant webserver with appserver.

Multiple SSL Certificates per IP

Since PHP 5.6.x allows to bind Multiple SSL Certificates to a single IP, we’ve passed on this functionality to you. With version 1.1.x appserver.io, you can enable this feature through a simple configuration option. Simply add the following lines to a server configuration:

...
<certificates>
    <certificate domain="appserver.dev" certPath="etc/appserver/appserver.pem" />
    <certificate domain="*.appserver.dev" certPath="etc/appserver/appserver-wildcard.pem" />
</certificates>
...

For more details about SSL configuration, please refer to our server configuration documentation.

Proxy Module

The Proxy Module provides full proxy functionality by supporting user defined logic in upstream types, which can be used for implementing custom behavior (e. g. load-balancing, HTTP caching, etc.).

The proxy configuration consists of two parts. The first part is within the container configuration. As an example, if you want to proxy a local Apache instance, you have to configure the upstream server as follows:

...
<upstreams>
    <upstream name="exampleBackend" type="\AppserverIo\WebServer\Upstreams\DefaultUpstream">
        <servers xmlns="">
            <server name="local-apache" type="\AppserverIo\WebServer\Upstreams\Servers\DefaultServer">
                <params xmlns="http://www.appserver.io/appserver">
                    <param name="address" type="string">127.0.0.1</param>
                    <param name="port" type="integer">80</param>
                    <param name="weight" type="integer">1</param>
                    <param name="maxFails" type="integer">10</param>
                    <param name="failTimeout" type="integer">30</param>
                    <param name="maxConns" type="integer">64</param>
                    <param name="backup" type="boolean">false</param>
                    <param name="down" type="boolean">false</param>
                    <param name="resolve" type="boolean">false</param>
                </params>
            </server>
    </upstream>
</upstreams>
...

The second part of the proxy configuration is found in the server configuration, which uses the configured upstream server. So, if your application has a folder test, and the requests should be handled by the Apache instance we configured before, you simply need to add a location with a file handler, which will forward the requests. Something like this:

...
<locations>
    <location condition="\/test\/.*">
        <fileHandlers>
            <fileHandler name="proxy" extension=".*">
                <params>
                    <param name="transport" type="string">tcp</param>
                    <param name="upstream" type="string">exampleBackend</param>
                </params>
            </fileHandler>
        </fileHandlers>
    </location>
</locations>
...

You can find more information about the Proxy Module configuration in our webserver documentation.

Auto Index Module

The Auto Index Module, defined with issue 700, enables auto generation of directory index on server, virtual host level or location level. The configuration is pretty simple, as only one parameter needs to be set to true. If, for example, the auto index functionality has to be enabled for a complete server, simply set the parameter autoIndex in the etc/appserver/appserver.xml file to true. This is what it would look like:

...
<server
        name="http"
         ...>
    <params>
        ...
        <param name="autoIndex" type="boolean">true</param>
        <param name="autoIndexTemplatePath" type="string">resources/templates/www/auto_index.phtml</param>
    </params>
</server>

After restarting the application server and pointing the browser to the directory, autoindexing is enabled. You should see a page similar to the image below:

Auto Index Module

It is also possible to customize the layout by setting the parameter autoIndexTemplatePath to a different template, which will be used to render the generated page.

You can read a more detailed description about the AutoIndex Module configuration in our webserver documentation.

Headers Module

The Headers Module allows admins and developers to append or override the response headers. This feature can be, as is the case with the configuration for most of the other modules, be done on server, virtual host or location level. To change the response header with the server signature, simply add the following lines to the server configuration:

...
<headers>
    <header type="response" name="Server" value="My Own Server" override="true"/>
</headers>
...

For a more detailed description about the Headers Module configuration, please refer to our webserver documentation.

Application Server

Finally, we released some important enhancements for the application server itself. These new and important features have a major impact on how applications can be built and what configuration options are available.

Application Configuration

A frequently requested and helpful new option is the possibility to access nearly all of the server or virtual host configuration parameters within the application itself. This means applications can define their own servers and virtual hosts, as well as override existing ones. This feature is enabled by default, but can be deactivated with a simple flag in the main server configuration, e. g. for a production environment.

These new configuration options have to be declared in new XML files (containers.xml and cron.xml) and are located in the application’s META-INF directory.

To deliver a simple virtual host configuration with an application, the file containers.xml in the applications META-INF directory needs the following content

<?xml version="1.0" encoding="UTF-8"?>
<containers xmlns="http://www.appserver.io/appserver">
    <container name="combined-appserver">
        <servers>
            <server name="http">
                <virtualHosts>
                    <virtualHost name="example.dev www.example.dev">
                        <params>
                            <param name="admin" type="string">info@appserver.io</param>
                            <param name="documentRoot" type="string">webapps/example</param>
                        </params>
                    </virtualHost>
                </virtualHosts>
            </server>
        </servers>
    </container>
</containers>

As a virtual host is always bound to a server, it is necessary to specify the container and the server name through the appropriate attributes.

In addition to the ability to configure/override server and virtual host configurations, a developer can also deliver a CRON configuration with his application, as described in the CRON section above.

You can find more informations about Application Configuration in our configuration documentation.

Doctrine Integration (@PersistenceUnit annotation)

Version 1.1.0 introduces a seamless Doctrine integration. The integration consists of three parts. The first part entails the Datasources, which describe the connection to a database. The second part entails the Persistence Units, which describe the Entity Manager and the Datasource to be used. The third part entails the Annotations used to inject the Entity Manager instance into the application’s components.

As Datasources have already been available since version 1.0.0, there was no clear concept when and how to use it. In our example application we demonstrated one possible way to use a Datasource to instantiate a Doctrine Enitity Manager instance. Since version 1.1.0, Persistence Units can be configured to reference datasources. This allows us to declare a Persistence Unit in an XML file META-INF/persistence.xml. This can be used by DI, via the @PersistencUnit annotation, to let the container inject an Entity Manager instance into an application’s components.

The short example below gives a brief introduction on how things will work. First, we define a Datasource describing a connection to a SQLite database, located in a file META-INF/test-ds.xml with the following lines:

<?xml version="1.0" encoding="UTF-8"?>
<datasources xmlns="http://www.appserver.io/appserver">
    <datasource name="appserver.io-example">
        <database>
            <driver>pdo_sqlite</driver>
            <user>appserver</user>
            <password>appserver</password>
            <path>META-INF/data/appserver_ApplicationServer.sqlite</path>
            <memory>false</memory>
        </database>
    </datasource>
</datasources>

The next step is to define the Persistence Unit. The file also has to be located under the application’s META-INF directory and MUST have the name persistence.xml. This file could have the following content

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://www.appserver.io/appserver">
    <persistenceUnits>
        <persistenceUnit name="ExampleEntityManager"
            interface="Doctrine\ORM\EntityManagerInterface"
            type="Doctrine\ORM\EntityManager"
            factory="AppserverIo\Appserver\PersistenceContainer\Doctrine\EntityManagerFactory">
            <metadataConfiguration type="annotation">
                <directories>
                    <directory>/common/classes/AppserverIo/Entities</directory>
                </directories>
                <params>
                    <param name="isDevMode" type="boolean">true</param>
                    <param name="useSimpleAnnotationReader" type="boolean">false</param>
                    <param name="proxyDir" type="string">false</param>
                </params>
            </metadataConfiguration>
            <datasource name="appserver.io-example"/>
        </persistenceUnit>
    </persistenceUnits>
</persistence>

The Persistence Unit references the Datasource with the value of the attribute name of the datasource node. These simple steps are all that is needed to build an Entity Manager instance and make it available within an application. In order to use the EM instance, e. g. in a Stateless Session Bean, a simple annotation is added to the bean, as shown below:

<?php
/**
 * @Stateless
 */
class MyStatelessSessionBean
{

    /**
     * The Doctrine EntityManager instance.
     *
     * @var \Doctrine\ORM\EntityManagerInterface
     * @PersistenceUnit(unitName="ExampleEntityManager")
     */
    protected $entityManager;

    /**
     * Returns an array with all existing entities.
     *
     * @return array An array with all existing entities
     */
    public function findAll()
    {
        // load all entities
        $repository = $this->entityManager->getRepository('AppserverIo\Entities\Sample');
        return $repository->findAll();
    }    
}

That’s it! More information is available in our persistence container documentation.

Lifecycle Callbacks for SFSB (@PostDetach, @PreAttach)

Last, but not least, we’ve added two new Lifecycle Callbacks for Stateful Session Beans, which enables a developer to execute code, before a Stateful Session Bean (SFSB) is re-attached to the Persistence Manager or after it is unloaded.

The Lifecycle Callbacks can be annotated with the @PostDetach and the @PreAttach annotations on one of the a SFSBs methods. These methods are useful, when a developer want to use non serializable resources in an SFSB, for example, a database connection.

The following example show’s how Lifecycle Callbacks can be annotated

<?php
/**
 * @Stateful
 */
class MyStatefulSessionBean
{

    /**
     * @PreAttach
     */
    public function foo()
    {
        // e. g. close a database connection here
    }
    
    /**
     * @PostDetach
     */
    public function bar()
    {
        // e. g. re-connect to the database here
    }
}

To read more about the Lifecycle Callbacks available in appserver and how they can be used, please refer back to our persistence container documentation.

Conclusion

We’re proud of the work done to the newest version of appserver, “Iron Knight”. It provides easy to use solutions for some of the most discussed problems of version 1.0.x. We will continue to be focused on giving developers the best tools available to build high performance and rock solid PHP web applications.

Since this blog post only gives a short introduction to the new features and because we know reading and understanding documentation isn’t everyone’s cup of tea, we’ve extended our example application with examples of all the new functionality described above. So, if you’re looking for best practices or how to’s, please have a look at the example application, which is also installed with our 1.1.0 Iron Knight release.

If you have any additional questions or feedback, feel free to contact us on our well frequented Gitter chat room. We’d love to hear from you!