Google Chrome Taking 16GB of my Macbook Air

I just found Chrome on Mac is consuming 16gb of my precious disk space. After some investigation, turns out Chrome is keeping all old version from auto update and they’re safe to delete.

Screen Shot 2015-11-23 at 8.34.05 pm

Here’s how to delete them:

  1. Open Finder, go to Applications, find Google Chrome
  2. Two finger tap (aka right click), “Show Package Contents”
  3. Navigate to Contents > Versions, delete anything other than the last version. Don’t forget to empty your trash

Managing Spring Security User Session

Ever wondered who is currently logged in to your app or how to kick them out? Evil_grin_emoticon. You can do it using SessionRegistry.

Screen Shot 2015-08-01 at 11.36.36 pm

(Disclaimer: UI is self-coded, not provided by Spring)

ntT5yBs

First, setup spring security configuration

Java config:

.and()
  .sessionManagement()
    .maximumSessions(1) // How many session the same user can have? This can be any number you pick
    .expiredUrl("/login?expired")
    .sessionRegistry(sessionRegistry)

And register the sessionRegistry bean:

@Bean(name = "sessionRegistry")
public SessionRegistry sessionRegistry() {
  return new SessionRegistryImpl();
}

Or XML config, place this below <security:http>:

  <security:session-management> 
      <security:concurrency-control max-sessions="1" expired-url="/login?expired" session-registry-alias="sessionRegistry"/>
  </security:session-management>

Now you can list currently active sessions

Inject a SessionRegistry and let’s see who’s currently logged in:

@Autowired
private SessionRegistry sessionRegistry;

public List<SessionInformation> getActiveSessions() {
  List<SessionInformation> activeSessions = new ArrayList<>();
  for(Object principal : sessionRegistry.getAllPrincipals()) {
    activeSessions.addAll(sessionRegistry.getAllSessions(principal, false));
  }
  return activeSessions;
}

SessionInformation object contains a lot of useful methods such as getPrincipal, getSessionId and getLastRequest. Have a look at the javadoc for more info.

What principal? I’m not in school anymore

Principal is just a fancy word for user in security speak. Note how SessionInformation returns a principal of type Object. If you use Spring Security your principal will most likely be the type of org.springframework.security.core.userdetails.User

Here’s how you can get the username from a User object:

SessionInformation session = ... // get the session info somehow
Object principalObj = session.getPrincipal();
if (principalObj instanceof User) {
  User user = (User) principalObj;
  return user.getUsername();
}

If you need to kick someone out

The use case of this is not just for when you hated a particular user so much, but if user permission is updated, then you have to invalidate all active sessions for it to take effect.

public void logoutSession(String sessionId) {
  SessionInformation session = sessionRegistry.getSessionInformation(sessionId);
  if (session != null) {
    session.expireNow();
  }
}

Enjoy

And thanks to SO user dimas for posting an answer that inspires this post.

Why You Should Use Java 8: NullPointerException Free Object Access Using Optional

If you haven’t you should read Tired of Null Pointer Exceptions? Consider Using Java SE 8’s Optional.

How many times does object traversal code like this frightens you?

String city = personRepository.getByUsername("bob").getAddress().getCity();

Yes it’s a looming NullPointerException bound to happen. Remember Murphy’s Law? Anything that can go wrong, will go wrong.

Here’s how we all used to make it safer in Java 7 <

  String city;
  Person person = personRepository.getByUsername("bob");
  if (person != null) {
    Address address = person.getAddress();
    if (address != null) {
      city = address.getCity();
      if (city == null) {
        city = "Unknown";
      }
    }
  }

whatifmeme

Java 8 lambda to the rescue:

String city = personRepository
                  .findByUsername("bob")
                  .flatMap(Person::getAddress)
                  .flatMap(Address::getCity)
                  .orElse("Unknown")
;

How does this work? flatMap and orElse are methods of Optional interface. In plain english flatMap(Person::getAddress) reads: apply the function getAddress belonging to the class Person and give me whatever return value getAddress has.

Of course we have to wrap the types used to store the values in the object with Option:

public class PersonRepository {
  public Option<Person> findByUsername(String username) {
    ...
  }
}

public class Person {
  private Option<Address> address;
  public Option<Address> getAddress() { return this.address; }
}

public class Address {
  private Option<String> city;
  public Option<String> getCity() { return this.city; }
}

No way! I don’t want to have to wrap all my property types with Optional / I’m using a 3rd part library and cannot refactor the types

Not a problem you can wrap them when you traverse the object:

String city = Optional.ofNullable(personRepository.findByUsername("bob"))
                .map(Person::getAddress)
                .map(Address::getCity)
                .orElse("Unknown");
;

Optional.ofNullable will create an Optional object with values that may be null. map is similar to flatMap except this one says: apply function X to this Optional and give me another Optional with whatever X’s return type.

One more reason to convince your boss / architect / team lead to upgrade your code into Java 8 :-). Enjoy.

Using ZeroMQ Java Binding

  1. Ensure you have ZEROMQ_HOME environment variable pointing to the root source package (and compiled jars/dlls). See the compilation guide for more info.
  2. Ensure %ZEROMQ_HOME%\java\lib\zeromq.jar is on the classpath. The best way to achieve this if you’re using Maven is to deploy it to your internal repository so your work colleague can reference it directly.

    To deploy to internal maven repo:

    C:\> cd %ZEROMQ_HOME%\java\lib
    
    C:\zeromq-4.0.5\java\lib> mvn deploy:deploy-file -Dfile=zmq.jar -DgroupId=my.company.zmq -DartifactId=zmq -Dversion=3.1.0 Durl=file:////path/to/my/company/maven_repository
    

    To add this dependency on your project, add this to your pom.xml:

    <dependency>
      <group>my.company.zmq</group>
      <artifactId>zmq</artifactId>
      <version>3.1.0</version>
    </dependency>
    
    ...
    
     <repositories>
      <repository>
        <id>my-company-internal</id>
        <url>file:////path/to/my/company/maven_repository</url>
      </repository>
    </repositories>
    
  3. Set java system property java.library.path to %ZEROMQ_HOME%\java\lib. Note that java doesn’t accept environment variable, so you have to resolve it yourself. If you’re running through command line:
    C:\> java -Djava.library.path=C:\zeromq-4.0.5\java\lib
    

    On application servers like tomcat, you’ll have to edit the start script or the Windows service configuration. This system property has to be set before runtime starts, doing System.setProperty(key, value) will not work.

  4. Add %ZEROMQ_HOME%\bin\x64 to PATH env var:
    C:\>SET PATH=%ZEROMQ_HOME%\bin\x64;%PATH%
    

    If deploying on production server, this need to be done via Windows Advanced System Configuration. Make sure you restart any VM so it can pick up the latest env vars

  5. If you’re deploying on production environment, only following folder layout is required:
    C:\zeromq-4.0.5
     +- bin
         +- x64
             +- libzmq.dll
     +- java
         +- lib
             +- jzmq.dll
    

See Also

ZeroMQ Windows Java Binding: Building libzmq.dll, jzmq.dll and zmq.jar Using Visual Studio 2012

Versions used in this article:

  • jzmq-3.1.0
  • ZeroMQ-4.0.5 source
  • jdk 1.6.0 (Update 34), Windows 64bit
  • Visual Studio 2012
  • Windows 7 64bit

Build Steps

  1. Download ZeroMQ 4.0.5 source code, inflate it to C:\zeromq-4.0.5 (or other folder to your liking). Set your ZEROMQ_HOME environment variable pointing to this folder.
  2. Download jzmq-3.1.0 source code, inflate it to %ZEROMQ_HOME%\java
  3. On %ZEROMQ_HOME%, open Visual Studio solution file builds\msvc\msvc10.sln. Switch the active profile to Release, and platform to x64. Perform Build Solution (F7). If successful you should get bin\x64\libzmq.dll
  4. On %ZEROMQ_HOME%\java, open Visual Studio solution file builds\msvc\msvc.sln. Switch the profile into Release
  5. Go to jzmq project property, edit the VC++ Directories. The include path has to correctly reference your jdk path (you can use environment variable like $(JAVA_HOME)). Similarly it also need reference to $(ZEROMQ_HOME)\include and ..\. ..\ is required so reference to config.hpp is not broken. Your Include Directories should end up similar like this:
    jzmq1
  6. Edit the Library Directories, and add $(JAVA_HOME)\lib and $(ZEROMQ_HOME)\lib. Your Library Directories should end up similar like this:
    jzmq2
  7. Do solution build. If all is successful you should end up with jzmq.dll and zmq.jar on %ZEROMQ_HOME%\java\lib
  8. You can now run the test program as mentioned on ZeroMQ Java Bindings doc:
    C:\>cd %ZEROMQ_HOME%\java\src\main\perf
    
    C:\zeromq-4.0.5\java\src\main\perf>set PATH=%ZEROMQ_HOME%\bin\x64;%PATH%
    
    C:\zeromq-4.0.5\java\src\main\perf>java -Djava.library.path=C:\zeromq-4.0.5\java\lib -classpath C:\zeromq-4.0.5\java\lib\zmq.jar;. local_lat tcp://127.0.0.1:5555 1 100
    

    Source code of these sample codes are available on %ZEROMQ_HOME%\java\src\main\perf in case you’re wondering what they do

See Also

Additional References

Checking for C++ 11 Support

Most c++ compilers define a constant named __cplusplus which indicates C++ 11 support. Hence you can write something like this (thanks Cygon for the SO reply)


#if __cplusplus <= 199711L #error This library needs at least a C++11 compliant compiler #endif [/cpp] On most g++, you can pass -std=c++11 to toggle C++ 11 support:

g++ -std=c++11 main.cpp

This is what I get when I try to output the __cplusplus constant with the flag set:


#include
using namespace std;

int main() {
cout << __cplusplus << endl; return 0; } [/cpp] [text] $ g++ -std=c++11 test.cpp $ ./a.out 201103 [/text] Visual C++ compiler version 2012 or above should come with near-complete C++ 11 support.

Working With Time In C++

Working with time with any programming language is always tricky, C++ is no exception.

Getting Current Time

Use the time function to get the current time. Note that time_t has no timezone information, it’s simply UTC offset from epoch (1 January 1970 00:00:00). In most platform it’s stored as 8 bytes integer.

#include <ctime>

int main(int argc, char** argv) {
  time_t now;
  time(&now);
  return 0;
}

Formatting / Printing Time

Use C-style strftime function to format time. Note that strftime takes a struct tm * as parameter, so we have to first convert the time_t. Use localtime to convert it into local time zone.


struct tm * now_tm = localtime(&now);
char now_str[100];
strftime(now_str, sizeof(now_str), “%F %T %z”, now_tm);
cout << now_str << endl [/cpp] The above pattern string will produce a time format like this: [text] 2015-03-12 12:11:45 +1000 [/text] strftime man page has an excellent explanation of the pattern string. If you want to convert into GMT timezone you can also use gmtime

Parsing Time

This is where things get even more trickier. Not until C++11 standard the language come with a built-in way to parse time strings. Prior to that you have to either write your own parsing function or use 3rd party library like boost.

Check here how to enable C++11 in your toolset.

The new C++11 standard comes with get_time function which can be used to parse string into a struct tm:


#include
#include
#include

using namespace std;

int main() {
struct tm tt;
cout << "enter time in YYYY-MM-DD HH:mm format: "; cin >> get_time(&tt, “%Y-%m-%d %H:%M”);
cout << put_time(&tt, “%d %b %Y, %H:%M %z\n”); return 0; } [/cpp] This code will produce output like this: [text] $ ./a.out enter time in YYYY-MM-DD HH:mm format: 2015-06-11 23:44 11 Jun 2015, 23:44 +1000 [/text]

Setting Up ZeroMQ C++ On Visual Studio

This article is tested against following version / configuration:

  • Visual Studio 2012 (V110) Platform Toolset
  • Win32
  • ZeroMQ 4.0.4
  • Runtime Library: Multi-threaded DLL (/MD)

Steps to setup ZeroMQ on a Visual Studio C++ project:

  1. Download and install ZeroMQ-4.0.4~miru1.0-x86.exe (or newer) from http://zeromq.org/distro:microsoft-windows
  2. Set ZEROMQ_HOME environment variable to C:\Program Files (x86)\ZeroMQ 4.0.4 (or wherever you installed it to)
  3. On Visual Studio project configuration, add $(ZEROMQ_HOME)\include to Configuration Properties -> VC++ Directories. Don’t forget to restart Visual Studio so it picks up the new environment variable
  4. Add $(ZEROMQ_HOME)\lib to Linker -> General -> Additional Library Directories
  5. Add libzmq-v110-mt-4_0_4.lib to Linker -> Input -> Additional Dependencies
  6. Get a copy of zmq.hpp from https://github.com/zeromq/cppzmq, place this somewhere on your project. This header file references zmq.h located at $(ZEROMQ_HOME)\include
  7. Once you’ve compiled your executable, place libzmq-v110-mt-4_0_4.dll on the same folder, otherwise ZeroMQ initialisation will cause runtime crash

And finally take a look at some excellent tutorial examples from zeromq.org website to get you started, in particular:

See Also

Setting Up Spring Security On Spring Boot Project

Here’s my simple requirements:

  • /admin/** path require ROLE_ADMIN
  • /login/**, /css/**, /js/**, **/favicon.ico can be accessed anonymously
  • any other path required ROLE_USER
  • login form

Here’s how to implement it on your Spring Boot project:

  1. Add the spring boot security starter dependency:
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
  2. Add a SecurityConfig class extending WebSecurityConfigurerAdapter and implement the path, user and roles requirements above
    @Configuration
    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
      @Override
      protected void configure(HttpSecurity http) throws Exception {
        http
          .authorizeRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/css/**", "/js/**", "/img/**", "**/favicon.ico").anonymous()
            .anyRequest().hasRole("USER")
            .and()
          .formLogin()
            .permitAll()
        ;
      }
      
      @Override
      public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
          .inMemoryAuthentication()
            .withUser("admin").password("admin321").roles("USER", "ADMIN").and()
            .withUser("jim").password("jim321").roles("USER");
      }
    
    }
    

    This setup only works assuming you have @ComponentScan on your main configuration class. By default Spring Security will provide a login form at /login but you can implement your own. I’ve also setup two users to test it

Using JSP On Spring Boot App

By default Spring Boot did not come with JSP support. Here’s how to set your app to use JSP:

  1. Set the project to use tomcat7-maven-plugin rather than spring-boot-maven-plugin
  2. Add / ensure following Maven dependencies are setup
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.tomcat</groupId>
      <artifactId>tomcat-jsp-api</artifactId>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
    </dependency>
    
  3. The Web MVC auto configuration feature of Spring Boot sets you up with a ViewResolver with blank suffix and prefix, hence you can place jsp in src/main/webapp/WEB-INF/test.jsp and have your controller return path to it
    @Controller
    @RequestMapping("/test")
    public class TestController {
      @RequestMapping(method = GET)
      public String test() {
        return "/WEB-INF/test.jsp";
      }
    }
    

Hope this helps!

Gerry's software development journey of trial, errors and re-trials