Best practice of html5 input for limited length

What you need is ,

  • Only numbers can be input
  • The length of input is limited to N, say 2
  • On mobile devices, a number pad will be shown

And the way to do it is:

<input type="number" pattern="[0-9]*" oninput="this.value=this.value.slice(0,2)"/>

If you are using material-ui, it will be

        type: "number",
        pattern: "[0-9]*" 

    onInput={(e: any)=>{ =,2)

Generate assertEquals(xxx, bean.getXxx()) for all the properties of a javabean

In intellij, create such a live template:

    public static void main(String args[]) {
        Class<?> clazz = $Bean$.class;
        String object = "$bean$";
        java.lang.reflect.Method[] methods = clazz.getMethods();
        for (java.lang.reflect.Method m : methods) {
            if ((m.getName().startsWith("get") || m.getName().startsWith("is") )&&  (!m.getName().equals("getClass")) &&  m.getParameterTypes().length == 0) {
                    "assertEquals(\"xxx\"," + object + "." + m.getName() + "()); "


Make sure chromedriver can run with Java selenium code, both in a real machine and in docker

Install chromedriver

You want to make the following line of code run successfully.

ChromeDriver driver = new ChromeDriver();

In windows, you need to download chrome driver from and put it in system’s path (An alternative is to set the executable file’s path as a system property “”, not beautiful)

In *nix or linux-based Docker, you can

apt update
apt install chromedriver -y   #for debian-based systems 

Options needed for ChromeDriver

        ChromeDriverService chromeDriverService = new ChromeDriverService.Builder().withWhitelistedIps("").build();//without this you may see " bind() returned an error, errno=99: Cannot assign requested address (99) "

        // without the following you may see "DevToolsActivePort file doesn't exist" 
        ChromeOptions chromeOptions = new ChromeOptions();
        if(isUnixBased()) {

        ChromeDriver driver = new ChromeDriver(chromeDriverService, chromeOptions);


Opinion: Don’t use class for data structure in typescript (2019). Use interface only

Always use interfaces instead

Problems of class:

  • Lots of frameworks such as Redux don’t support class instances. They only support plain objects. There are tools that can convert plain objects to class instances, but the point below makes it awkward.
  • Given a variable “someType: SomeType” in the code, you don’t know if it is a plain object or a class instance. So you don’t know if you can call its methods, or if it is OK to call plainToClass() to convert it to a class instance.

Use spring +aspectj in Spring boot

public class YourApplication ...{
public class YourAspect {

	@Before("execution(public * com..*Manager.*(..))")
	public void doAdvice(JoinPoint joinPoint) {...}

Enable google analytics with react-router

One way of doing this is to create your own Router class, which extends the one from the framework; and inside this Router class you put in the tracking logic:

class MyRouteComponent extends React.Component<Props, State> {

    constructor(props: Props) {
        this.state = {currentUserRefreshed: false};

        if (isProdEnv()) {

    trackPage(pageUrl:string) {
        ReactGA.set({page: pageUrl});

    toPageUrl(location: Location) {
        return location.pathname +;

    componentDidMount() {

        if(isProdEnv() && this.props.location){

    render() {

My first react HOC + Redux component in Typescript

The logic: Show a component only if the user logged in

import React from 'react';
import {connect} from "react-redux";

interface AuthenticatedUserOnlyProps {
    authenticated: boolean

function mapStateToProps(state: State) {    
    return {
        authenticated: state.authenticated

export function authenticatedUserOnly<T>(WrappedComponent: React.ComponentType<T>) {
    class FinalComponent extends React.Component<AuthenticatedUserOnlyProps > {
        public render() {

            const {authenticated, ...otherProps} = this.props;
            if (authenticated) {
                return <WrappedComponent {...(otherProps as T)}/>
            } else {
                return null;

    return connect(mapStateToProps, null)(FinalComponent);

To use it, just

render() {
    const someComponent = authenticatedUserOnly(SomeComponent); 

    return {
           {someComponent }

Springfox for 204 response

What you need to,

  • Return ResponseEntity<Void>
  • Set the @ResponseStatus for your rest controller’s method

If you don’t do that, you will get ResponseEntity as the response class in your swagger json, and you will get both 200 and 204 as your successful response code, which is not correct because your method only returns 204, no 200.

    @RequestMapping(value = "...", method = RequestMethod.POST)
    @ApiOperation(value = "...")
    @ApiResponses(value = {
            @ApiResponse(code = 204, message = "success")
    public ResponseEntity<Void> someMethod(){}

IOS Safari showing a blank page when coming back to a React Component


When you go to a react component, then go to another, and finally come back, the react component is showing blank, or half-blank.


If you inspect the page with the mobile safari inspector , you can see the elements are there, but safari just refuse to show the data on the screen.

In my case, this seems to be related with data reloading when I come back to the component. It reloads the data in its componentDidAmount() then re-render. Safari may not perform well enough to handle this kind of re-rendering.


A workaround is to not reload the data when you come back to the component. You can do this by checking if the data exists, and only loads the data if not existing.

It comes with a price: when you come back to the component, you are not seeing the data that’s up-to-data. There are a few things you can do to make it up:

  • A delayed data re-loading
  • Always reload the data 24 hours (e.g.) after last data loading
  • Very important: destroy the data if a user logs out to make sure a different user won’t see the first user’s data