Java Ninja Chronicles By Norris Shelton

Things I learned in the pursuit of code

This is an example of how to make a global exception handler. Our company had a need to work with an external vendor. They needed to get error states (person not found, account disabled, insufficient access, etc). These were mapped to various HTTP status codes and they wanted a JSON body with specific information in it. Springframework provides the ability to specify an exception handler that can process exceptions for multiple controllers.

The business logic was handled by creating Exception objects for each type of exception that was needed. Each custom exception had an empty constructor and a constructor that accepts the message. This is an example:

package com.javaninja.exception;

/**
 * Missing, invalid or expired token.
 */
public class AuthorizationException extends Exception {

    /**
     * Constructs a new exception with {@code null} as its detail message. The cause is not initialized, and may
     * subsequently be initialized by a call to {@link #initCause}.
     */
    public AuthorizationException() {
    }

    public AuthorizationException(String message) {
        super(message);
    }
}

Once you have the exceptions, you are ready to create something that can handle them. Springframework used to only support exception handlers that were within the individual controllers.

As of Spring MVC 3.2, they now support an exception handler that can handle exceptions for multiple controllers via @ControllerAdvice. This takes an optional property basePackages. The basepackages property allows you to set which packages this exception handler handles exceptions for. You can not specify it for the exception handler to apply to all controllers or you can list a package or multiple packages that are comma-separated.

An example of an exception handler that handles all packages is:

@ControllerAdvice
public class MyExceptionHandler {
    //...
}

An example of an exception handler that handles a single package is:

@ControllerAdvice(basePackages = "com.javaninja.services")
public class MyExceptionHandler {
    //...
}

An example of an exception handler that handles multiple packages is:

@ControllerAdvice(basePackages = "com.javaninja.services,com.javaninja.other")
public class MyExceptionHandler {
    //...
}

Now that you have a class that can handle exceptions, it’s time to get to work. To handle an exception, you annotate a method with @ExceptionHandler. There is an optional value property. You can specify one or more exceptions to handle. If you don’t list any exceptions, the exception handler will handle all exceptions.

An example from the Springframework documentation of an exception handler method that handles a single exception is:

@ExceptionHandler(IOException.class)
public ResponseEntity<String> handleIOException(IOException ex) {
// prepare responseEntity
return responseEntity;
}

An example that handles several exceptions is:

@ExceptionHandler(value = {IOException.class, SqlException.class})
public ResponseEntity<String> handleIOException(IOException ex) {
// prepare responseEntity
return responseEntity;
}

An example that handles all exceptions is:

@ExceptionHandler
public ResponseEntity<String> handleIOException(IOException ex) {
// prepare responseEntity
return responseEntity;
}

These methods returned a ResponseEntity. This offers you a tremendous amount of flexibility. Much more than I needed in my case.

If you are working on JSON services, you can use normal things like @ResponseBody to translate an object into it’s JSON representation.

    @ExceptionHandler(IOException.class)
    @ResponseBody
    public MyExceptionResponse handleThisException(Exception e) {
        return createResponse(e);
    }

Returning a certain HTTP status code after encountering an exception isn’t an uncommon thing. To do this, you use @ResponseStatus. There is a required value of HttpStatus type. An example is:

    @ExceptionHandler(IOException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public MyExceptionResponse handleThisException(Exception e) {
        return createResponse(e);
    }

Now, to bring this all together. This is an full example:

package com.javaninja.exception;

import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.validation.ConstraintViolationException;

/**
 * Handles exceptions for the Java Ninja.
 * @author norris.shelton
 */
@ControllerAdvice
public class ThisExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * Handle invalid request exceptions.
     * @param e exception object to be handled
     * @return exception response as a JSON body
     */
    @ExceptionHandler(ClassNotFoundException.class)
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ResponseBody
    public MyExceptionResponse handleBadRequestException(Exception e) {
        return createResponse(e);
    }

    /**
     * Handle authorization exceptions.
     * @param e exception object to be handled
     * @return exception response as a JSON body
     */
    @ExceptionHandler(value = {CGIServerException.class, AbandonedObjectException.class})
    @ResponseStatus(value = HttpStatus.UNAUTHORIZED)
    @ResponseBody
    public MyExceptionResponse handleAuthorizationException(Exception e) {
        return createResponse(e);
    }


    /*
     * Create the response body
     */

    /**
     * Create the response object.
     * @param e exception object to be handled
     * @return exception response object
     */
    private MyExceptionResponse createResponse(Exception e) {
        logger.info("{}  message: {}", e.getClass().getSimpleName(), e.getMessage());
        MyExceptionResponse exceptionResponse = new MyExceptionResponse(e.getClass().getSimpleName(),
                                                                        e.getMessage(),
                                                                        DateTime.now());
        logger.debug("exception response: {}", exceptionResponse);
        return exceptionResponse;
    }
}

When this exception handler encounters an exception, it returns a specific error code and the JSON payload appears similar to:

{
    "code": "TxnNotFoundException",
    "msg": "Unable to find the requested transaction",
    "timestamp": "2015-07-30 12:51:54"
}

July 30th, 2015

Posted In: Java, java ninja, Javaninja, Spring

Tags: , , ,

Leave a Comment

There are several times when you need to specify a location in a Springframework configuration. An example is

<util:properties id="gsiProperties" location="classpath:gaming-adapter-default.properties"/>

A location is represented as a Resource. There are several ways to specify where to find the resource.

  • classpath: This represents a resource that should be retrieved from the classpath. It works the way a normal classloader does. The first match wins. Package names can also be represented as file directories (e.g. /this/that/my.properties
  • classpath:* This means that ALL resources that match the given name must be obtained, then merged to form a single resource. Meaning multiple property files could be mapped to. The sum of them would be used to supply the properties.
  • file: This is used to access a file system resource. This can be an absolute path or relative path.
  • http: This is used to access resources via HTTP protocol with a URL.
  • ftp: this is used to access a resource via FTP protocol.
  • blank This relies upon the implementation of the underlying context. For web applications, this utilizes the Servlet context.

July 28th, 2015

Posted In: java ninja, Javaninja, Spring

Tags: , , , , ,

Leave a Comment

Intellij IDEA doesn’t show hidden files in the file chooser dialog on Mac OS/X. This can be frustrating when you are trying to find files that are always in a hidden directory, such as Maven files. There are two ways around this.

This will enable it for the current window

ctrl + shift + .

There is another solution, but it involves editing the registry. Hit the following keys to access the Find Action menu.

cmd + shift + a

Once there, scroll down to ide.mac.file.chooser.show.hidden.files. Check the checkbox and select Close and away you go.

July 28th, 2015

Posted In: IntelliJ, java ninja, Javaninja, Mac, OS/X

Tags: , , ,

Leave a Comment

A common problem is to retrieve a property from a property files and to use that value within your code. The Springframework has several tools that make that very easy to do.

The first thing to do is to create your properties file. Mine contains the following:

aggregatorId=gsi
igpUrl=http://localhost:8080/igp-services
defaultSupplierId=voi

Next, you need to make Spring aware of the properties file. To do this, we will use the util schema. Line 4 shows that the properties has an id value. This allows us to later use that idid.key, instead of key.

xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
...
<util:properties id="gsiProperties" location="gaming-adapter-default.properties"/>

Now that you have the properties available to Spring, it’s time to use them. Notice that we are using Spring Expression Language (SpEl) to inject the value(…) of the key. Normally, I would use @Autowired or @Resource(name=”…”) to inject the properties object as a map, then call get(…) on the map. SpEl gives you an additional notational choice to inject the data. @value(…) can be placed on fields, methods, method parameters and constructor parameters. Inside the @value, you can use #{…}. You do not need # for predefined variables (e.g. @value({systemProperties.property})). If the property cannot be listed directly because it contains a period, etc, you can place it within square brackets with a single tick. An example is @Value(#{systemProperties[‘user.region’]}).

    @Value("#{gsiProperties.igpUrl}")
    private String igpUrl;

    @Value("#{gsiProperties.aggregatorId}")
    private String aggregatorId;

    @Value("#{gsiProperties.defaultSupplierId}")
    private String defaultSupplierId;
...
    model.setIdAggregator(aggregatorId);
    model.setIdGameSupplier(defaultSupplierId);

July 23rd, 2015

Posted In: Java, java ninja, Javaninja, SpEl, Spring

Tags: , , , ,

Leave a Comment

HTML5 is making geolocation much, much easier to do. It is now a standard API and it’s pretty easy to do.

    The Geolocation API is supported by the following browser versions and up:

  • Chrome 5.0
  • Firefox 3.5
  • Android 2.0
  • Iphone 3.0
  • IE 9.0+
  • Safari 5.0
  • Opera 10.6

The basic functionality to get the user’s current geolocation is accessed by:

<script>
     navigator.geolocation.getCurrentPosition(success, error, positionOptions);
</script>

The error handler and the options are optional. My signature is as follows:

<script>
     navigator.geolocation.getCurrentPosition(
          handleGeolocationSuccess,
          handleGeolocationError,
          positionOptions
);
</script>

It is also possible watch a user’s position. If you watch a user’s position, then you don’t have to poll it. The browser will notify you when the user’s location changes.

This is how the watch functionality is accessed:

<script>
     var id = navigator.geolocation.watchPosition(success, error, positionOptions);
</script>

The id is needed to stop the watch functionality.

<script>
     navigator.geolocation.clearWatch(id);
</script>

The positionOptions object is used to specify options to the geolocation API. The definition of the positionOptions object is as follows:

  • enableHighAccuracy – boolean. Require high accuracy (e.g. GPS).
  • timeout – milliseconds. How long should the code wait till it determines that it can’t get a location
  • maximumAge – the maximum age of a previous location that can be used. Use the last position that the browser has as long as that position is less than N milliseconds old. Set to 0 to require the current position immediately.

An example of the positions object is:

{enableHighAccuracy: true, timeout: 5000, maximumAge: 60000}

The full example is below:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Java Ninja Geolocation prototype</title>
</head>
<body>
    <button onclick="getCurrentGeolocation()">Locate Me!!!</button>
    <button onclick="watchGeolocation()">Watch Me!!!</button>
    <button id="stopWatchingGeolocation" style="display: none" onclick="stopWatchingGeolocation()">
        Stop watching Me!!!
    </button>

    <script>
        /** Variable to make seconds more readable. */
        var seconds = 1000;  // 1000 milliseconds = 1 second

        /** Positions Object to contain all of the settings that we want for the geolocation.getCurrentPosition call. */
        var positionOptions = {
            /** require high accuracy (e.g. GPS). */
            enableHighAccuracy: true,
            timeout: 5 * seconds,
            /**
             * Use a position that is up to a minute old.
             * Set to 0 to ask for the current position right now.  Makes it faster and less expensive for the user if
             * they are getting repeated requests.
             */
            maximumAge: 60 * seconds
        };

        /** The geolocation watch id.  This is used to stop the watch. */
        var watchGeolocationId = 0;

        /**
         * Get the user's current geolocation.
         */
        function getCurrentGeolocation() {
            navigator.geolocation.getCurrentPosition(
                    handleGeolocationSuccess,
                    handleGeolocationError,
                    positionOptions
            );
        }

        /**
         * Watch the user's geolocation.
         */
        function watchGeolocation() {
            watchGeolocationId = navigator.geolocation.watchPosition(
                    handleGeolocationSuccess,
                    handleGeolocationError,
                    {enableHighAccuracy: true, timeout: Infinity, maximumAge: 0}
            );
            // Used old school so the example wouldn't have to pull in Jquery
            document.getElementById("stopWatchingGeolocation").style.display = "block";
        }

        /**
         * Stop watching the user's geolocation.
         */
        function stopWatchingGeolocation() {
            navigator.geolocation.clearWatch(watchGeolocationId);
            // Used old school so the example wouldn't have to pull in Jquery
            document.getElementById("stopWatchingGeolocation").style.display = "none";
        }

        /*
         * Geolocation handler functions
         */


        /**
         * Success handler for geolocation.getCurrentPosition.
         * @param position
         */
        function handleGeolocationSuccess(position) {
            var latitude = position.coords.latitude;
            var longitude = position.coords.longitude;
            var accuracy = position.coords.accuracy;

            alert('latitude=' + latitude + "\nlongitude=" + longitude + "\naccuracy=" + accuracy + " meters");
        }

        /**
         * Error handler for geolocation.getCurrentPosition.
         * @param err
         */
        function handleGeolocationError(err) {
            if (err.code == 1) {
                alert('PERMISSION_DENIED - User declined to provide geolocation data');
            } else if (err.code == 2) {
                alert('POSITION_UNAVAILABLE - Network is down or GPS satellites are unavailable')
            } else if (err.code == 3) {
                alert('TIMEOUT - Unable to determine location within the allotted time')
            }
        }
    </script>
</body>
</html>

July 9th, 2015

Posted In: Geolocation, HTML, HTML5

Tags: , ,

Leave a Comment

In a previous post, I showed how to declare an error label container for jquery validation messages. http://javaninja.net/2010/12/change-where-jquery-validation-messages-are-displayed/.

Today, we had a problem where the markup of the page required us to need to specify for this particular field, display the messages here. The default behavior of showing the messages by the fields was still desired, but the mark-up was preventing this. Checker was being added by Jquery Uniform dynamically. It was restricted to width=”25″ and height=”25″ to force the checkbox to a certain size. The problem is that the regular Jquery Validation error messages defaults to placing the error message after the target element. Unfortunately, this places it within the div that is limiting its size.

<div class="x2-top row">
    <div class="col-md-9  uniformed">
        <div id="acceptedTermsDiv checker">
            <input type="checkbox" 
                   name="acceptedTerms" 
                   id="acceptedTerms" 
                   style="width:20px;" 
                   value="true" 
                   tabindex="6"/>
            <span class="tooltip_text" 
                  data-toggle="tooltip" 
                  data-placement="bottom" 
                  title="You must accept the Terms and Conditions." 
                  data-container="#acceptedTermsDiv">
                <label for="acceptedTerms">I Accept The <a href="#" class="inline" id="termsLink">Terms &amp; Conditions</a></label>
            </span>                                                                                   
        </div>
    </div>
</div>

One way to solve this is to use a custom errorPlacement to force the messages to a custom location.

<div class="x2-top row">
    <div class="col-md-9  uniformed">
        <div id="acceptedTermsDiv checker">
            <input type="checkbox" 
                   name="acceptedTerms" 
                   id="acceptedTerms" 
                   style="width:20px;" 
                   value="true" 
                   tabindex="6"/>
            <span class="tooltip_text" 
                  data-toggle="tooltip" 
                  data-placement="bottom" 
                  title="You must accept the Terms and Conditions." 
                  data-container="#acceptedTermsDiv">
                <label for="acceptedTerms">I Accept The <a href="#" class="inline" id="termsLink">Terms &amp; Conditions</a></label>
            </span>                                                                                   
        </div>
    </div>
</div>

The custom errorPlacement will look like this:

errorPlacement: function(error, element) {
    if (element.attr("type") == "checkbox") {
        error.insertAfter($(element).closest(".checker").closest('div'));
    } else {
        error.insertAfter(element);
    }
}

June 17th, 2015

Posted In: java ninja, Javaninja, javascript, JQuery

Tags: , , , , , , ,

Leave a Comment

The previous article regex validation with jquery validation plugin laid the foundation for creating custom validation methods.

One thing I ran into was the case where multiple validations were created for a password, but they only test for the existence of one character that matches the regex. Meaning, does the password contain a lower-case letter? The advantage of using multiple validations, is that the user can be told which types of characters they need to make their password validate correctly.

I needed to validate that a password contains at least one lower-case letter, at least one upper-case letter, at least one number, and at least one symbol. First, I created the custom validations.


/**
 * Custom validator for contains at least one lower-case letter
 */
$.validator.addMethod("atLeastOneLowercaseLetter", function (value, element) {
    return this.optional(element) || /[a-z]+/.test(value);
}, "Must have at least one lowercase letter");

/**
 * Custom validator for contains at least one upper-case letter.
 */
$.validator.addMethod("atLeastOneUppercaseLetter", function (value, element) {
    return this.optional(element) || /[A-Z]+/.test(value);
}, "Must have at least one uppercase letter");

/**
 * Custom validator for contains at least one number.
 */
$.validator.addMethod("atLeastOneNumber", function (value, element) {
    return this.optional(element) || /[0-9]+/.test(value);
}, "Must have at least one number");

/**
 * Custom validator for contains at least one symbol.
 */
$.validator.addMethod("atLeastOneSymbol", function (value, element) {
    return this.optional(element) || /[!@#$%^&*()]+/.test(value);
}, "Must have at least one symbol");

Once the validators were created, now it was time to use them.

<script>
    $(function () {
        $("#change-password").validate({
            rules: {
                password: {
                    required: true,
                    atLeastOneLowercaseLetter: true,
                    atLeastOneUppercaseLetter: true,
                    atLeastOneNumber: true,
                    atLeastOneSymbol: true,
                    minlength: 8,
                    maxlength: 40
                }
            }
        });
    });
</script>

An alternative way to specify the rules is

$("#password").rules("add", {
    required: true,
    minlength: 8,
    maxlength:40,
    atLeastOneLowercaseLetter: true,
    atLeastOneUppercaseLetter: true,
    atLeastOneNumber: true,
    atLeastOneSymbol: true
});

June 13th, 2015

Posted In: java ninja, Javaninja, javascript, JQuery

Tags: , , , ,

Leave a Comment

Bootstrap 3 tooltips are fairly easy to use. They also offer excellent cross-browser support while also being responsive.

If you are already using Bootstrap 3, then it is fairly easy to start using the tooltips. The first step is to add the HTML markup.

<a href="#"
     data-toggle="tooltip"
     title="My tooltip text">Tooltip target</a>

That is fairly straight forward. The title contains the text that will be displayed in the tooltip. data-toggle is a custom attribute and is used by the required javascript to trigger the markup as a tooltip.

The required javascript is

<script>
    $(function () {
        $('[data-toggle="tooltip"]').tooltip();
    });
</script>

That’s all it takes for a basic tooltip. Sometimes you need to customize the functionality. The default behavior is to trigger the tooltip on click. Sometimes you need other triggers, hover for example. This can be accomplished by adding data-trigger.

<a href="#"
     data-toggle="tooltip"
     data-trigger="hover click"
     title="My tooltip text">Tooltip target</a>

If you want to style the text, all you need to do is add normal class attribute. In my case, I made a css style especially for this purpose.

<a href="#"
     class="tooltip_text"
     data-toggle="tooltip"
     title="My tooltip text">Tooltip target</a>

By default, HTML markup is not displayed as HTML when it is included as part of the tooltip text. This can be enabled by adding data-html.

<a href="#"
     data-html="true"
     data-toggle="tooltip"
     title="My tooltip text">Tooltip target</a>

We did encounter a problem with using an <a> as the HTML element. The page will attempt to scroll to the anchor when clicked. We overcame this by using a tag.

<span data-toggle="tooltip"
      title="My tooltip text">
  Tooltip target
</span>

The default placement for the tooltips is above the trigger. Use data-placement to specify left, right or bottom.

<a href="#"
     data-placement="bottom"
     data-toggle="tooltip"
     title="My tooltip text">Tooltip target</a>

June 10th, 2015

Posted In: Bootstrap, CSS, HTML

Tags: , , , , ,

Leave a Comment

Grunt, grunt, grunt. This is my first gruntfile. Once you get in the groove, it’s pretty easy to write them quickly.

module.exports = function (grunt) {

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        clean: ['build'],
        less: {
            current: {
                files: [
                    {
                        expand: true,
                        cwd: "current/styles",
                        src: [
                            'global/**/*.less',  // need to process the global css separately from the rest
                            'modules/**/*.less'
                        ],
                        dest: 'build/temp/css',
                        ext: '.css'
                    }
                ]
            },
            working: {
                files: [
                    {
                        expand: true,
                        cwd: "working/styles",
                        src: [
                            'global/**/*.less', // need to process the global css separately from the rest
                            'modules/**/*.less'
                        ],
                        dest: 'build/temp/css-working',
                        ext: '-working.css'
                    }
                ]
            }
        },
        concat: {
                css: {
                    options: {
                        sourceMap: true
                    },
                    files: {
                        'build/compiled/css/<%= pkg.name %>.css': [
                            'bootstrap-3.3.4/dist/css/bootstrap.css',
                            'build/temp/css/global/igaming.css',
                            'build/temp/css/modules/**/*.css'],  // note would be better to use files created in less task via something like'<%= less.working.files.dest %>'
                        'build/compiled/css/<%= pkg.name %>-working.css' : [
                            'bootstrap-3.3.4/dist/css/bootstrap.css',
                            'build/temp/css-working/global/igaming.css',
                            'build/temp/css-working/modules/**/*.css'  // note would be better to use files created in less task via something like'<%= less.working.files.dest %>'
                        ]
                    }
                },
                js: {
                    options: {
                        separator: ';',
                        sourceMap: true
                    },
                    files: {
                        'build/compiled/js/<%= pkg.name %>.js': [
                            // load jquery, bootstrap, then the rest
                            'current/scripts/jquery/*.js',
                            'bootstrap-3.3.4/dist/js/bootstrap.js',
                            'current/scripts/libs/*.js',
                            'current/scripts/js/*.js',
                            'current/scripts/igaming/*.js'
                        ],
                        'build/compiled/js/<%= pkg.name %>-working.js': [
                            // load jquery, bootstrap, then the rest
                            'working/scripts/jquery/*.js',
                            'bootstrap-3.3.4/dist/js/bootstrap.js',
                            'working/scripts/libs/*.js',
                            'working/scripts/js/*.js',
                            'working/scripts/igaming/*.js'
                        ]
                    }
                }
        },
        uglify: {
            current: {
                options: {
                    sourceMap: true,
                    sourceMapIncludeSources: true,
                    sourceMapIn: 'build/compiled/js/<%= pkg.name %>.js.map'
                },
                files: {
                    'build/compiled/js/<%= pkg.name %>.min.js': 'build/compiled/js/<%= pkg.name %>.js' // wouldn't use '<%= concat.js.dest %>', for some reason
                }
            },
            working: {
                options: {
                    sourceMap: true,
                    sourceMapIncludeSources: true,
                    sourceMapIn: 'build/compiled/js/<%= pkg.name %>-working.js.map'
                },
                files: {
                    'build/compiled/js/<%= pkg.name %>-working.min.js': 'build/compiled/js/<%= pkg.name %>-working.js' // wouldn't use '<%= concat.js_working.dest %>', for some reason
                }
            }
        },
        cssmin: {
            options: {
                sourceMap: true
            },
            target: {
                files: {
                    'build/compiled/css/<%= pkg.name %>.min.css': ['build/compiled/css/<%= pkg.name %>.css'],
                    'build/compiled/css/<%= pkg.name %>-working.min.css': ['build/compiled/css/<%= pkg.name %>-working.css']
                }

            }
        },
        copy: {
            // builds the /assets webapp by copying the /webapp directory,
            // then copying the compiled css and js resources
            webapp: {
                files: [
                    {
                        expand: true,
                        cwd: 'webapp',
                        src: '**',
                        dest: 'build/assets'
                    }
                ]
            },
            compiled: {
                files: [
                    {
                        expand: true,
                        cwd: 'build/compiled',
                        src: '**',
                        dest: 'build/assets/compiled'
                    }
                ]
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-contrib-copy');


    // Default task(s).
    grunt.registerTask('default', ['clean', 'less', 'concat', 'uglify', 'cssmin', 'copy']);




    //grunt.registerTask("concat-css", "Concatenates the CSS files into a CSS file per section", function () {
    //
    //    // read all subdirectories from your modules folder
    //    grunt.file.expand("build/css").forEach(function (topDir) {
    //        console.log('topDir=' + topDir);
    //
    //        //grunt.file.setBase(topDir);
    //        // read all subdirectories from your modules folder
    //        grunt.file.expand("build/css").forEach(function (dir) {
    //            console.log('dir=' + dir);
    //
    //            console.log("cssFiles=" + cssFiles);
    //
    //            // get the current concat config
    //            var concat = grunt.config.get('concat') || {};
    //
    //            // set the config for this modulename-directory
    //            concat[cssFiles] = {
    //                //cwd: topDir,
    //                src: dir + '**/*.css',
    //                dest: dir + '.css'
    //            };
    //            // save the new concat configuration
    //            grunt.config.set('concat', concat);
    //        });
    //        // set the base to where it is supposed to be so that Grunt works as expected
    //        //grunt.file.setBase('../..');
    //    });
    //    // when finished run the concatenations
    //    grunt.task.run('concat');
    //});


};

June 9th, 2015

Posted In: grunt, Javaninja, javascript

Tags: , , , ,

Leave a Comment

Creating a SOAP client for a SOAP web service is very straight forward when using CXF. Given a WSDL url or a WSDL file, create a project with a pom.xml containing the following:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.rightnow.ws</groupId>
    <artifactId>rightnow</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>3.0.4</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <configuration>
                            <wsdlOptions>
                                <wsdlOption>
                                    <wsdl>https://twinspires--tst.custhelp.com/cgi-bin/twinspires.cfg/services/soap?wsdl</wsdl>
                                </wsdlOption>
                            </wsdlOptions>
                        </configuration>
                        <goals>
                            <goal>wsdl2java</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

When you run mvn compile, it will generate classes in the generated-sources/cxf directory.

The next step is to use the service client. The normal usage pattern is below. The service is instantiated, then the port is retrieved.

package com.rightnow.ws.wsdl.v1_2;

import com.rightnow.ws.metadata.v1_2.MetaDataClass;
import org.junit.Test;

import javax.xml.datatype.XMLGregorianCalendar;
import java.util.List;

import static org.junit.Assert.assertNotNull;

/**
 * @author norris.shelton
 */
public class TestRightNowSyncService {

    @Test
    public void testName() throws Exception {
        RightNowSyncService rightNowSyncService = new RightNowSyncService();
        RightNowSyncPort rightNowSyncPort = rightNowSyncService.getRightNowSyncPort();

        XMLGregorianCalendar metaDataLastChangeTime = rightNowSyncPort.getMetaDataLastChangeTime();
        assertNotNull(metaDataLastChangeTime);

        List<MetaDataClass> metaDataClasses = rightNowSyncPort.getMetaData();
        assertNotNull(metaDataClasses);

    }
}

April 1st, 2015

Posted In: CXF, Java, java ninja, Javaninja, Maven, SOAP

Tags: , , , , ,

2 Comments

Next Page »
LinkedIn Auto Publish Powered By : XYZScripts.com