Wordpress/Contact Form 7 post request to Java Servlet

Post to Twitter

This article is an upgraded version of Joomla/RSForms post request to Java Servlet.

The use case is the same: Calling a Java Servlet, after submitting a form. The servlet should read the form data and start e.g. the creation of a license file.

The form plugin Contact Form 7 is very popular for Wordpress. It's powerful and easy to use.

But sadly, it doesn't support custom php scripts, only custom Javascript calls. So it's possible to add custom javascript calls with predefined hooks. Not exactly what we want because Javascript functions run on client side and not in the same context as the php backend.

It wasn't possible to implement missing features without coding php, but it was not tricky.

What we did to call a Java Servlet?

1. Register a custom module

Modified wp-content/plugins/contact-form-7/settings.php

public static function load_modules() {
    ...
    self::load_module( 'submit' );
    self::load_module( 'text' );
    self::load_module( 'textarea' );
    self::load_module( 'hidden' );

    self::load_module( 'sibvisions' );
}

Added load_module('sibvisions');

2. Create the new module

Created wp-content/plugins/contact-form-7/modules/sibvisions.php

<?php
/**
 ** Module for SIB Visions.
 **/

add_action('wpcf7_submit', 'wpcf7_sibvisions_submit', 10, 2);

function wpcf7_sibvisions_submit($contactform, $result)
{
    if ($contactform->in_demo_mode() || $contactform->is_true('do_not_store'))
    {
        return;
    }

    $servletURL = $contactform->additional_setting('sib_servletURL');

    if (empty($servletURL[0]))
    {
        error_log('Servlet URL is not set in form!');
        return;
    }

    $cases = (array)apply_filters('wpcf7_sibvisions_submit_if',
                                  array('spam', 'mail_sent', 'mail_failed'));

    if (empty($result['status']) || ! in_array($result['status'], $cases ))
    {
        return;
    }

    $submission = WPCF7_Submission::get_instance();

    if (!$submission || ! $posted_data = $submission->get_posted_data())
    {
        return;
    }

    if (isset($posted_data['g-recaptcha-response']))
    {
        if (empty($posted_data['g-recaptcha-response']))
        {
            return;
        }
    }

    $fields_senseless = $contactform->scan_form_tags(
                                        array('feature' => 'do-not-store'));

    $exclude_names = array();

    foreach ( $fields_senseless as $tag )
    {
        $exclude_names[] = $tag['name'];
    }

    $exclude_names[] = 'g-recaptcha-response';

    foreach ($posted_data as $key => $value)
    {
        if ('_' == substr($key, 0, 1) || in_array($key, $exclude_names))
        {
            unset($posted_data[$key]);
        }
    }

    $url = str_replace('"', "", $servletURL[0]);
    $url = str_replace("'", "", $url);

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

    $data = array();

    foreach ($posted_data as $post => $value)
    {
        if (is_array($value))
        {
            foreach ($value as $post2 => $value2)
            {
                $data[] = $post.'[]='.urlencode($value2);
            }
        }
        else
        {
            $data[] = $post.'='.urlencode($value);
        }
    }

    curl_setopt($ch, CURLOPT_POSTFIELDS, implode('&', $data));
 
    $data = curl_exec($ch);

    if (curl_errno($ch))
    {
        wp_mail('noreply@sibvisions.com', 'Service error',
                'Call to service ('.$url.') failed with error ('.curl_error($ch).')');
    }
    else
    {
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE)
       
        if ($http_code != 200)
        {
            wp_mail('noreply@sibvisions.com', 'Service error',
                    'Call to service ('.$url.') failed with error ('.$data.')');
        }
    }
   
    curl_close($ch);
}

The script is based on module flamingo.php because it had all useful validations.

Be careful, because the script will be applied to all your forms. It's form independent.

3. Additional setting

The only thing you'll need is am additional setting (for your form):

sib_servletURL:'https://server/services/registration'

This setting configures the servlet to use for the form. If you don't configure a servlet, the module will do nothing!

DONE

The new module will forward all form data to the servlet. The servlet is the same as in our original article - no changes needed.

JVx Kitchensink, a simple JVx showcase application

Post to Twitter

As we've just noticed, we've neglected so far to properly introduce the JVx Kitchensink, a (very) simple showcase application for JVx and its controls. We'd like to rectify that now.

A simple showcase, not a demo application

The JVx Kitchensink can be found on GitHub and is available under an Apache 2.0 License. It demonstrates nearly all controls and components of the JVx framework and simple and easy to digest examples.

JVx Kitchensink

As some of you might know, there is also the JVx Hello World Application. The Kitchensink does not intend to supersede the Hello World Application, quite the opposite, the intention is to complement it. The Hello World Application is demonstrating how to quickly and easily set up a complete JVx application and have it up and running in mere minutes, with focus on the lifecycle of the application. The Kitchensink on the other hand demonstrates each individual component and control of JVx, and completely neglects the "normal" lifecycle of a JVx application.

Samples

The button bar on the left allows you to quickly access each example, for example the one about databinding.

JVx Kitchensink - Databinding

Newly added has been the feature that you can now see the source code of the selected sample right inside the Kitchensink, simply select the "Source" tab.

JVx Kitchensink - Databinding (Source)

Here I have to mention the awesome RSyntaxTextArea, which is a Swing component and provides highlighting and editing functionalities for source code, and is obviously used by us.

Regarding the lifecycle

As said before, the Kitchensink as not a good example of the lifecycle of a JVx application, as outlined in JVx Reference, Application Basics.

Packaged and ready

The Kitchensink does already come as a ready to use Eclipse project with launchers, so all you have to do is import it into Eclipse and be ready to go. There is also an Ant build script and instructions on how to launch the readily compiled jars.

Last but not least, it does provide a nice test bed for most of the functionality of JVx and demonstrates most concepts in a neatly packaged manner. We've been using it excessively during the development of the JVx JavaFX frontend bindings and it can be as simply used to test new concepts and custom components.

Once again, the link to the KitchenSink GitHub repository