Spring Web: Encode ‘+’ Value Using UriComponentsBuilder

PROBLEM

Given the following code…

final String url = UriComponentsBuilder.
        fromHttpUrl('https://server').
        queryParam('var', '{var}').
        buildAndExpand('1 2+3').
        encode().
        toString()

When using Spring Web 4.3.18.RELEASE, the URL is properly encoded:-

https://server?var=1%202%2B3

However, when using version between 5.0.0.RELEASE and 5.0.7.RELEASE, the URL containing “+” value does not get encoded:-

https://server?var=1%202+3

SOLUTION

There is a ticket opened regarding this breaking change.

To properly encode “+” value, use 5.0.8.RELEASE or later.

Then, ensure encode() is invoked before buildAndExpand(..):-

// Produces https://server?var=1%202%2B3
final String url = UriComponentsBuilder.
        fromHttpUrl('https://server').
        queryParam('var', '{var}').
        encode().
        buildAndExpand('1 2+3').
        toString()

The above code can be further shorten to this:-

// Produces https://server?var=1%202%2B3
final String url = UriComponentsBuilder.
        fromHttpUrl('https://server').
        queryParam('var', '{var}').
        build('1 2+3').
        toString()

 

 

Advertisements

macOS + Eclipse: The ‘X’ Executable Launcher was Unable to Locate its Companion Shared Library

PROBLEM

When attempting to launch Eclipse-based app (ex: MyApp.app) on Mac, the following error is thrown:-

The 'MyApp' executable launcher was unable to locate 
its companion shared library.

SOLUTION

This problem seems to occur on macOS Sierra and later.

When unzipping the app, the lingering extended attributes prevent the app from launching.

To fix this, run the following command to remove these extended attributes:-

xattr -c MyApp.app

Then, double click MyApp.app to launch it.

React + Recompose: Calling Multiple HOC Wrappers

PROBLEM

Sometimes, wrapping a React component with multiple High Order Components (HOC) can get rather unwieldy and unreadable.

For example:-

import React from 'react';
import { withRouter } from 'react-router-dom';
import { withStyles } from 'material-ui/styles';
import withWidth from 'material-ui/utils/withWidth';

class MyComponent extends React.PureComponent {
	// ...
}

export default withRouter(withStyles(styles)(withWidth()(MyComponent)));

SOLUTION

To fix this, we can leverage recompose library.

Now, we can rewrite the above example like this:-

import React from 'react';
import { withRouter } from 'react-router-dom';
import { withStyles } from 'material-ui/styles';
import withWidth from 'material-ui/utils/withWidth';
import compose from 'recompose/compose';

class MyComponent extends React.PureComponent {
	// ...
}

export default compose(
  withRouter,
  withStyles(styles),
  withWidth(),
)(MyComponent);

Keep in mind, the HOC order defined in compose(..) is important.

Webpack + ESLint: Automatically Fix ESLint Errors

PROBLEM

Given the following webpack.config.js

module.exports = {
  ...
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.js?$/,
        loader: 'eslint-loader',
        exclude: /node_modules/,
      },
	  ...
    ],
  },
  ...
};

When running any Webpack command, ESLint may find violations and halt the entire process with the following error message:-

/path/to/front-end-stack/src/js/components/home/Home.js
  43:11  error  Expected indentation of 6 space characters but found 10  react/jsx-indent
  44:14  error  Expected indentation of 6 space characters but found 13  react/jsx-indent

x 2 problems (2 errors, 0 warnings)
  2 errors, 0 warnings potentially fixable with the `--fix` option.

SOLUTION

Certain errors (ex: trailing commas, wrong indentation, extra semicolon) are easily fixable.

There’s no need to halt the process and wait for developers to fix these obvious errors.

To configure ESLint to automatically fix these “soft” errors, add the following options block to the above rule:-

module.exports = {
  ...
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.js?$/,
        loader: 'eslint-loader',
        exclude: /node_modules/,
        options: {
          fix: true,
        },		
      },
	  ...
    ],
  },
  ...
};

If you are using any VCS, remember to commit any file changes.

PHP + Composer: The Process “php -S 0.0.0.0:8080 -t public index.php” Exceeded the Timeout of 300 Seconds

PROBLEM

Given the following composer.json

{
  ...
  "scripts": {
    "start": "php -S 0.0.0.0:8080 -t public index.php"
  }
}

When running composer start

The PHP built-in web server stops with the following error message…

[Symfony\Component\Process\Exception\ProcessTimedOutException]                              
The process "php -S 0.0.0.0:8080 -t public index.php" exceeded the timeout of 300 seconds.  

SOLUTION

There are several ways to extend the timeout value, but here is one way to do it through composer.json.

To extend the timeout value from 300 seconds to 2000 seconds, add the following config block in composer.json:-

{
  ...
  "scripts": {
    "start": "php -S 0.0.0.0:8080 -t public index.php"
  }
  "config": {
    "process-timeout": 2000
  }
}

To disable web server timeout completely, set process-timeout to 0:-

{
  ...
  "scripts": {
    "start": "php -S 0.0.0.0:8080 -t public index.php"
  }
  "config": {
    "process-timeout": 0
  }
}

Slim: Class ‘X’ Not Found

PROBLEM

Let’s assume we have the following project structure with src/model/Person.php created…

.
├── composer.json
├── composer.lock
├── logs
├── public
├── src
│   ├── model
│   │   └── Person.php
│   ├── dependencies.php
│   ├── middleware.php
│   ├── routes.php
│   └── settings.php
├── templates
├── tests
└── vendor

… and the class may look something like this…

// src/main/Person.php

class Person
{
    public $name;
    public $age;

    public function __construct(string $name, int $age)
    {
        $this->name = $name;
        $this->age = $age;
    }
}

… and it is being used in other file…

// src/routes.php

use Slim\Http\Request;
use Slim\Http\Response;

$app->get('/[{name}]', function (Request $request, Response $response, array $args) {
    $person = new Person('mike', 50);

    // ... do something
    return ...
});

When hitting the given route from the browser, we get the following error:-

Type   : Error
Message: Class 'Person' not found
File   : /path/to/app/src/routes.php
Line   : 7

SOLUTION #1: Using import/require

One way to solve this is to use include or require statement:-

// src/routes.php

require 'model/Person.php';

use Slim\Http\Request;
use Slim\Http\Response;

$app->get('/[{name}]', function (Request $request, Response $response, array $args) {
    $person = new Person('mike', 50);

    // ... do something
    return ...
});

SOLUTION #2: Using autoloading

Another approach is to leverage PSR-4 autoloading.

First, create a namespace in Person.php:-

// src/main/Person.php

namespace App\Model;

class Person
{
    public $name;
    public $age;

    public function __construct(string $name, int $age)
    {
        $this->name = $name;
        $this->age = $age;
    }
}

Second, in the file that consumes that model, specify a use statement to alias that model so it doesn’t need to be fully qualified with the given namespace in order to use it:-

// src/routes.php

use App\Model\Person;
use Slim\Http\Request;
use Slim\Http\Response;

$app->get('/[{name}]', function (Request $request, Response $response, array $args) {
    $person = new Person('mike', 50);

    // ... do something
    return ...
});

Third, in composer.json, create the autoload block and specify the namespace mapping in it:-

{
  ...
  "autoload": {
    "psr-4": {
      "App\\Model\\": "src/model/"
    }
  },
  "autoload-dev": {
    "psr-4": {
      "Tests\\": "tests/"
    }
  },
  ...
}

Finally, run composer dump-autoload to regenerate vendor/composer/autoload_psr4.php. This file keeps track the list of classes needed to be included in the project.

Spring Security: Propagating Security Context to Spawned Threads

PROBLEM

Let’s assume we have the following Parent class…

@Service
class Parent {
    @Autowired
    Child child

    void run() {
        println "Parent: ${SecurityContextHolder.context.authentication?.principal}"

        child.run()

        println "Parent: Done"
    }
}

… and Child class…

@Service
class Child {
    @Async
    void run() {
        Thread.sleep(500)
        println "Child: ${SecurityContextHolder.context.authentication?.principal}"
    }
}

Let’s also assume the user has successfully logged in and Spring Security has set up the user authentication info.

The Parent will spawn a new thread (through @Async) to run Child.

When invoking the Parent, this is what we see:-

Parent: USER_PRINCIPAL
Parent: Done
Child: null

The Child, for some reason, doesn’t get the receive the user authentication info.

SOLUTION

By default, SecurityContextHolder uses MODE_THREADLOCAL to store the user authentication info. As a result, this info is not accessible to methods outside the current execution thread.

To fix this, configure SecurityContextHolder to use MODE_INHERITABLETHREADLOCAL to pass the user authentication info to other spawned threads.

@Configuration
@EnableAsync
class AppConfig {
    AppConfig() {
        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL)
    }
}

When invoking the Parent again, now the Child will also receive the user authentication object:-

Parent: USER_PRINCIPAL
Parent: Done
Child: USER_PRINCIPAL