Skip to content

belgattitude/pjb-starter-springboot

Repository files navigation

Build Status License: MIT

Easy starter to package a PHPJavaBridge server with custom dependencies in minutes.

While both the recent PHPJavaBridge server fork and this starter can be easily customized (in pretty much the same way), the latter features a standalone .jar build (embedded Tomcat 8.5+) in addition to the standard .war file and offer support for Spring boot for additional customizations. Those features comes with a cost in term of dependencies size (overhead of 11Mb comparing to barebone phpjavabridge) although no speed differences have been measured between both bundles.

Be aware that this starter does not register the PHPCGIServlet by default and thus does not require a php-cgi installation in order to run (a common issue when installing the bridge). While most use cases does not requires it (Java->PHP), its activation is possible, see the FAQ.

Requirements

Features

  • Recent soluble PHPJavaBridge servlet registered.
  • Compatible with the soluble-japha client.
  • Based on spring boot with thymeleaf architecture.
  • Gradle init-scripts examples for managing dependencies (jasperreports, poi, corenlp...).
  • By default, does not require a php-cgi present (see the FAQ about PHPCGIServlet)
  • Dashboard landing page with json monitoring address.
  • Build easily manageable from the command line (gradle and init-scripts).
  • Provides a standalone .jar with an embedded tomcat (in addition to standard .war file).

Quick start

Packaging and deploying a customized PHPJavaBridge server could be done in 3 steps:

  1. Clone the project (or download and unzip the release archive)

    $ git clone https://github.com/belgattitude/pjb-starter-springboot
    $ cd pjb-starter-springboot
  2. Build the .war and .jar files

    Example of build with jasperreports and mysql jdbc connector. See the '-I' parameter in the command below. Refer to the init-scripts doc for other recipes.

    $ ./gradlew build -I init-scripts/init.jasperreports.gradle -I init-scripts/init.mysql.gradle

    Your builded files are saved in the build/libs, type ls -la build/libs to list them.

  3. Run standalone server .jar from the command line (optional, skip to 4 for tomcat deployment)

    $ java -jar ./build/libs/JavaBridgeStandalone.jar -Dserver_port=8090

    Open your browser and check the landing page located at http://localhost:8090.

  4. Alternatively deploy the .war on Tomcat (when not using standalone)

    Tomcat deployment is the preferred way over the standalone .jar mode for production. While the standalone is also running under tomcat (embedded tomcat 8.5+), the Tomcat provided with your OS is a better choice regarding standard location of log files as well as boot startup integration.

    cp ./build/libs/JavaBridgeTemplate.war /var/lib/tomcat8/webapps/MyJavaBridge.war

    Wait few seconds and point your browser to http://localhost:8080/MyJavaBridge.

    Note that the /MyJavaBridge/ URI corresponds to the war filename as copied in the webapps folder... feel free to adapt to your own needs. To re-deploy (deploy an updated version), simply copy the new .war file, Tomcat will apply the changes automatically.

Don't forget to read the full documentation below, especially security considerations when exposing the PHPJavaBridge server to the outside world, some common issues with memory in the FAQ and read the soluble-japha doc for PHP/Java interactions.

Documentation

1. Get the project

Clone the project

$ git clone https://github.com/belgattitude/pjb-starter-springboot/ 

If you intend contribute or want to keep a track of changes, consider making your own fork first and refer it in the clone command instead of the main project.

2. Build

Call the build gradle task:

$ ./gradlew build 

And check the build\libs directory for the following files:

File Description Approx. size
JavaBridgeStandalone.jar Standalone server with an embedded Tomcat 8.5+. +/- 32Mb
JavaBridgeTemplate.war War file, ready to drop into Tomcat webapps folder. +/- 12Mb

Approx. size is given as a reference of the current default build.

3. Run the PHPJavaBridge server.

The following example use bootRun task to run the server. Choose Tomcat deployment or the standalone mode for production.

$ ./gradlew bootRun 
# or specify the port with gradle bootRun -Dserver.port=8090

And point your browser to http://localhost:8090.

4. Connect from PHP

Create a php project in a directory of your choice and install the soluble-japha client.

$ composer require soluble/japha

Set the connection to the running phpjavabridge server (port 8090 by default)

<?php

require 'vendor/autoload.php'; // for composer autoload

use Soluble\Japha\Bridge\Adapter as BridgeAdapter;

$ba = new BridgeAdapter([
    'driver' => 'Pjb62', 
    'servlet_address' => 'localhost:8090/servlet.phpjavabridge'
]);

$system = $ba->javaClass('java.lang.System');
echo $system->getProperties()->get('java.vm_name');

5. How to distribute, run or deploy

WARNING The phpjavabridge server is not supposed to be run on a public facing server and its use should be limited to interactions on the same host/network with the php client. Do not run it as root neither as it exposes the JVM methods through the network. In its default configuration the pjb⁻starter example does not provide any security mechanisms so any url with an extension of '*.phpjavabridge' could be remotely exploited.

5.1 Standalone (embedded tomcat8)

To run simply

$ java -jar ./build/libs/JavaBridgeStandalone.jar -Dserver_port=8090 

And point your browser to http://localhost:8090 to check.

5.2 Deploy on Tomcat 7/8

Copy to the Tomcat webapp directory to deploy:

cp ./build/libs/JavaBridgeTemplate.war /var/lib/tomcat8/webapps/MyJavaBridge.war

wait few seconds and point your browser to http://localhost:8080/MyJavaBridge.

Note that the port may vary and the URI (or server context) is taken from the deployed filename. In this example: 'MyJavaBridge', feel free to change.

Repeat operation whenever you need to (re-)deploy.

6. Advanced customizations

Have a look a those files:

File Desc
build.gradle Customize your dependencies here (jasper...), version,...
main/resources/application.yml Various spring-boot application settings
main/java/io/soluble/pssb/Application.java Where servlets, filters... are registered.
settings.gradle Customize the root project name

Modify for your usage and rebuild with grade bootRun to check.

Note that the welcome page is handled by the main/java/io/soluble/pssb/mvc/IndexController.java with dependencies in the 'templates' and 'static' subdir in resources folder.

Faq

OutOfMemory errors ?

With the self-contained tomcat

> export JAVA_OPTS=-Xmx512m -XX:MaxPermSize=128M

If deployed on Tomcat

$ vi /etc/default/tomcat8

Look for the Xmx default at 128m and increase

JAVA_OPTS="-Djava.awt.headless=true -Xmx512m -XX:+UseConcMarkSweepGC"

and restart

sudo service tomcat8 restart

How can I monitor that the bridge runs ?

The pjb-starter-springboot includes a very basic PingController, you can call it on http://localhost:8090/ping.json, you should see

{
    "date": 1484919571831,
    "success": true,
    "message": "PHPJavaBridge running"
}

How to add libraries to the builded war (jar) ?

You can either add your dependencies directly in the build.gradle file or use the init-script method. The latter is preferred if you prefer to keep the build.gradle file intact.

  1. Preferred method: Use the init-script method.

    Have a look to the init-script method documentation.

  2. Alternative method: Modify the build.gradle file: Just open the build.gradle and check the runtime (or compile) sections.

    dependencies {
        // Spring-boot stuffs
        providedRuntime "org.springframework.boot:spring-boot-starter-tomcat:${spring_boot_version}"
        testCompile "org.springframework.boot:spring-boot-starter-test:${spring_boot_version}"
        compile "org.springframework.boot:spring-boot-starter-web:${spring_boot_version}"
        compile ("org.springframework.boot:spring-boot-starter-thymeleaf:${spring_boot_version}") {
            exclude group: 'org.codehaus.groovy', module: 'groovy'
        }
        compile "org.springframework.boot:spring-boot-devtools:${spring_boot_version}"  // Useful for dev (auto disabled on prod)
        compile "com.google.code.gson:gson:2.8.0"  // Deps for the ping address
    
        // PHPJavaBridge
        compile("io.soluble.pjb:php-java-bridge:${pjb_version}") {
            // In sprint-boot, you can exclude javax.servlet and log4j
            exclude group: 'javax.servlet', module: 'javax.servlet-api'
        }
    
        /** #######################################################
         *  Here you can add runtime dependencies to the project
         *  -------------------------------------------------------
         *  Those dependencies will be included available in the
         *  builded war file. Alternatively you may register deps
         *  through the 'init-script' method.
         *  (check 'init-scripts/README.md' folder for insights)
         *  #######################################################
         */
    
        // example: mysql jdbc connector
    
        /*runtime "mysql:mysql-connector-java:6.+"*/
    
    }

    Have a look to maven repo to quickly find your deps

    For PHP users, gradle might not sound familiar. In the context of adding libraries, you can consider it as a package manager like composer, npm... To add or define dependencies
    simply edit the dependencies section of the build.gradle file. Generally in the 'runtime' subsection.

How to start at boot ?

If you use the Tomcat deployment it should start by default. With the self-container tomcat, ask google for "supervisord spring boot".

BootRun support

BootRun task is really useful when developping and allows hot reloading when you customize css, html pages...

$ ./gradlew bootRun 
# or specify the port with gradle bootRun -Dserver.port=8090

And point your browser to http://localhost:8090.

How to enable the Java->PHP feature ?

By default this template does not enable Java->PHP by default. So if you intend to use PHP from Java, you must add to the Application.java the following methods:

public class Application extends SpringBootServletInitializer {


    /// Normal initialization sequence

    /**
     * Register the php.java.servlet.fastcgi.FastCGIServlet
     * <p>
     * It replaces the following section found in the original web.xml config:
     * <p>
     * <pre>
     * {@code
     * <servlet>
     *     <servlet-name>PhpCGIServlet</servlet-name>
     *     <servlet-class>php.java.servlet.fastcgi.FastCGIServlet</servlet-class>
     *     <load-on-startup>0</load-on-startup>
     * </servlet>
     * <servlet-mapping>
     *     <servlet-name>PhpCGIServlet</servlet-name>
     *     <url-pattern>*.php</url-pattern>
     * </servlet-mapping>
     * }
     * </pre>
     */
    @Bean
    public ServletRegistrationBean phpCGIServletDispatcherRegistration() {

        FastCGIServlet phpJavaServlet = new io.soluble.pjb.servlet.fastcgi.FastCGIServlet();
        ServletRegistrationBean registration = new ServletRegistrationBean(
                phpJavaServlet);
        registration.addUrlMappings("*.php");
        registration.setLoadOnStartup(0);
        return registration;
    }

    /**
     * Register the php.java.servlet.PhpCGIFilter
     * <p>
     * This filter extend the servlet spec 2.2 "url-pattern"
     * to handle PHP PATH_INFO: *.php/something?what=that.
     * Remove it, if you don't need this feature.
     * <p>
     * <pre>
     * {@code
     * <filter>
     *     <filter-name>PhpCGIFilter</filter-name>
     *     <filter-class>php.java.servlet.PhpCGIFilter</filter-class>
     * </filter>
     * <filter-mapping>
     *     <filter-name>PhpCGIFilter</filter-name>
     *     <url-pattern>/*</url-pattern>
     * </filter-mapping>
     * }
     * </pre>
     */
    @Bean
    public FilterRegistrationBean someFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new io.soluble.pjb.servlet.PhpCGIFilter());
        registration.addUrlPatterns("/*");
        //registration.addInitParameter("paramName", "paramValue");
        registration.setName("PhpCGIFilter");
        registration.setOrder(1);
        return registration;
    }

}
  

And ensure you have the php-cgi installed and available on your system.

An example page main/webapp/index.php page is already provided as a starting point.... Try http://localhost:8090/index.php

How to enable debugging ?

Debugging can be enabled with the standalone server:

$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
       -jar ./build/libs/JavaBridgeStandalone.jar

Status

  • Modernized JavaBridgeTemplate.jar example
    • JDK8, spring boot, thymeleaf.
    • JavaBridgeServlet registered PHP->Java- (from php use the soluble-japha client.
    • PhpCGIServlet registration example Java->PHP (disabled by default, doc exists)
    • Original PhpJavaBridge config properties in the original web.xml (like location of the php-cgi executable...)
  • Service landing page
    • Refactored welcome landing page.
    • Ping address for monitoring.
    • Display server/java infos
  • Documentation
    • How to customize (WIP)
    • Basic security recipes, incl. bind on localhost
    • Document how to add local jar deps (out of maven)

Contribute

Feel free to fork and submit pull requests.

Credits