Debian VM setup

This article is for setting up Debian on VirtualBox.

Download Debian

Go to the official site of Debian;
In Getting Debian page, download the small installation image (32-bit/64-bit).

Install Debian

Create a Debian VM in VirtualBox;
Insert the Debian ISO into the empty slot in Setting/Storage/Controller: IDE;
Start the VM and follow the steps to install Debian.

Install Guest Additions Driver

Start user session (login) in command line (Ctrl + Alt + F1/F7 to switch between GUI and command line);
Execute sudo apt-get install build-essential linux-headers-$(uname -r);
In the VM window, select Insert Guest Addition CD Image... under Device menu;
Execute sudo bash /media/cdrom/autorun.sh

Setup Shared Folders

Open Devices/Shared Folders/Shared Folders Settings
Under Shared Folders, click adds new shared folder;
Choose Folder Path, and check Auto-mount and Make Permanent, and click OK
Option 1: sudo nano /etc/group and edit the line starts with vboxsf to vboxsf:x:[number (don't change)]:[username1],[username2],...
Option 2: sudo adduser [username] vboxsf

Setup Host-only Network

Go to File/Preference/Network;
Click Adds new host-only network, and take a note of the ip address (referred as noted ip/netmask);
ifconfig is deprecated, use ip addr show or abbreviated as ip a to check network settings;
Still can use /sbin/ifconfig after sudo apt-get install net-tools;
Option 1 – peremptory: sudo /sbin/ifconfig eth1 [noted ip] netmask [noted netmask]
Option 2 – permanent: sudo nano /etc/network/interfaces

auto eth1
iface eth1 inet static
# the noted ip address
address 192.168.55.1
# the noted netmask
netmask 255.255.255.0
# the network of the above ip address you need to calculate
network 192.168.55.0
# the broadcast of the above ip address you need to calculate
broadcast 192.168.55.255

This blog may not be up to date. Please see the original post from Blogger http://ift.tt/2t8Ssir
via IFTTT.

Quick Start with Nashorn engine

As a replacement, Nashorn succeeded Rhino engine in JDK8 to provide performant JavaScript reflection. There are many real world products built in Java which have scripting portals for users to customize the system, e.g. ServiceNow (although it still uses Rhino by the time this article is written).
Before jumping into Java code, I just want make a very short intro to command line execution using jjs. Simply start bin/jjs.exe by typing jjs in command line after you got system path parameter set up.

$ jjs
jjs> exit()

Start JavaScript engine in Java

To evaluate JavaScript in Java, javax.script.ScriptEngine is used:

ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript"); // Using default JS engine, i.e. Nashorn
engine.eval("print('hello world!');"); // JS code is essentially a String in Java

Invoke JavaScript Functions from Java

Each ScriptEngine has its own namespace. (In JavaScript point of view, each ScriptEngine hosts one global scope.) Functions within it can run by normal JavaScript calls, as well as Java invocation:

engine.eval("function fun (name) {return 'hello ' + name;}; print(fun('Jianzhao'));");
Invocable invocable = (Invocable) engine;
Object result = invocable.invokeFunction("fun", "William");
System.out.println(result + " : " + result.getClass());

Invoke Java Method from JavaScript

To successfully invoke any Java method, you need a full class name including package path, and should not violating Java security constraint:

package ca.ljz;

import javax.script.*;

public class Cls {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("JavaScript");
        engine.eval("var Cls = Java.type('ca.ljz.Cls'); print(new Cls().meth('Will'));");
    }
    public String meth(String name) {
        return "hello "+ name;
    }
}

This blog may not be up to date. Please see the original post from Blogger http://ift.tt/2pKWy0p
via IFTTT.

Introduce to the Advanced Features of HAL

In Get Start with HAL, I went through the basic steps to setup a Spring Boot project and get HAL resource to work. This article is for you to check out some relatively advanced features used in a real word project called STARS. The features to be introduced include typical structure of an HAL project, handling composite primary keys, applying security constraints and so on.

Prerequisite

To be able to understand this article, you need to know the basis of HAL, Database, and Aspect Oriented Programming. You can find more information by following the link on each topic. In addition, since this article references a lot of code in project STARS, you may also need a runtime to download and run the project.

Example Project Synopsis

Sport Telemetry and Report System (STARS), a project adopting HAL, provides a web portal for users to store, manage, review and analyze the movement trajectory and body positioning data of their sport sessions. The version to be referencing in this article is v1.0.0-Alpha.

Structure of an HAL project

As a standard of RESTful Web Services, HAL inherits characteristics of REST, i.e. a clear separation between frontend and backend makes an HAL project to be standalone. It doesn’t care what type of clients to cooperate with.
As a Java implementation of HAL, Spring Framework features HAL through Spring Data REST. To better provide HAL standardized web API, Spring Data REST adopts aspect oriented programing (AOP) paradigm. Unlike traditional layered architecture, AOP allows developers to focus on special operations. Spring HAL automatically provides default CRUD operations. They are interceptable on different aspects to enable customized security constraints, content manipulations, associated operations, and so on.

Handling Composite Key

Composite Primary Key is a very common practice in database. To get it to work with HAL, there are 3 things you need to take care of: embedded primary key, JSON Representation, and conversion.

Embedded Primary Key

In JPA, composite primary key is also called embedded id, which is a special object containing all the columns of the primary key. In the example project, Record is a domain class representing the table stars_record, which has owner and title columns as a composite primary key. To represent this composite primary key, we need a special object called RecordPK as an embedded id.

JSON Representation

Once you have the embedded id, the project still cannot work as expected because it doesn’t know how to represent id in the self-reflect URL since the id contains more than one part. To specify the format of the id, you need to override toString method in the embedded id object. Check toString() in RecordPK, you will find that each part of composite key is delimited by & sign.

PK Conversion

So far, we have the way to represent composite primary key properly. The last thing is to convert the self-reflect URL back to the embedded id object. To do that, you need to implement a BackendIdConverter as a service. You should list all the domains that contain embedded id, and provide convertors for them. In addition, link toString method of embedded id objects to this service to make self-reflect URL to be properly displayed.

Apply Security Check

In Spring Data REST, the most common practice of securing the application would be just using Spring Security. This article is not about Spring Security, but the idea of how to apply it in an HAL project. So, if you are interested in how it is configured in the example project, you can still trace from WebSecurityConfig.java and read the comments.
To apply security on Record for example, you need to know what methods of the repository are provided by Spring. As we declared the interface RecordRepository, Spring will proxy this interface and its methods, and provides HAL REST APIs. You will find all the methods in RecordRepository.java.
From previous section, we talked about AOP. In RecordRepository, I used annotations as the way to adopt AOP to interfere the invocation of each method. @PreAuthorize is the only annotation I used for security check, although, there are many other annotations can be used in different scenario.
Instead of explaining every single annotation and its value, I would like to just pick a typical one:

@Override
@PreAuthorize("hasRole('ADMIN')")
Iterable<Record> findAll();

This method provides a web interface to return all the records in a JSON format when an HTTP GET request being sent to http://localhost:8080/rest/records. If there is no @PreAuthorize annotation, anyone can get all records in the system, which should not be the case. We want only admin users to be able to perform this query. So, by saying ” hasRole(‘ADMIN’)”, users without admin privilege will not be allowed to invoke this method. In this way, the project can be secured safely and efficiently.

Conclusion

In this article, we went through some advanced, but also commonly used features of Spring Data REST, which is a Java implementation of HAL. Since HAL and Spring Data REST are really big topics, I’m sure you will find more when doing the actual development. However, this article talks about the most important concepts you have to know, and I hope you enjoy working with HAL.

This blog may not be up to date. Please see the original post from Blogger http://ift.tt/2od7HEZ
via IFTTT.

Introduce to Winter Security

Winter Security is one of the most important components of Winter Framework. It enhances security constraints adopted by the server application and eases development in the best possible ways. Developing web services with Winter Security can really simplify the security logic and reduce boilerplate code without giving up the flexibility of the program.

Prerequisites

To be able to understand Winter Security, you need to know Java EE architecture since Winter is a complement for Java EE in the security aspect. If you don’t know Java EE architecture, the official tutorial would be a perfect starting point. To be more specific, the security part is relatively more important. In addition, knowledges of database, basic Java concepts and build tools are expected, e.g. SQL, Java project build path, Apache Maven, etc.
If you want to give a shot with limited knowledge in Java EE, it is OK. Once you have basic exposure to Java web, e.g. Servlet, JSP, etc., you should still be able to setup Winter Security by reading this blog. A nice thing about Winter Security is the simplicity it provides, which makes it to automatically fit in your project and start working behind the scene.

What does Winter Security do for you?

Winter Security provides authentication and authorization services for Java EE web applications. Authentication service is to exam if a user is whom he said who he is. Accordingly, authorization service is to exam if a user has the permissions to access what needs those permissions.

Why to use Winter Security over others?

Most of security frameworks are complex because they aim to provide general solutions to all development scenarios. Moreover, some older frameworks do not have a design to suit modern needs. Although, Winter Security requires a moderate understanding of Java EE platform, it still is a light weight and fairly easy to use security framework. In addition, most Java developers already know very well about Java EE platform anyway, there is no barrier for them to employ Winter Security as a light weight security framework.
Winter Security also summarizes other frameworks and adopts concepts such as User-Role-Permission authorization, Security Realm, Customizable Handlers, etc. These features make Winter Security strong enough to handle most web development needs.

Conditions of using Winter Security

Winter Security depends on Java EE 7 technologies. It means your project must be a Java EE project, and it ought to be deployed to a Java EE 7 Full Platform Compatible Implementations, e.g. GlassFish, Jboss, etc.

Concepts of Winter Security

Before start installing Winter Security, you have to understand some of the basic concepts of web security. Most security frameworks, including Winter Security are following the similar structure. There are 3 concepts to know in the first place:
1. User-Role-Permission authorization;
2. Security Realm;
3. Customizable Handlers.

User-Role-Permission authorization

User-Role-Permission (URP) authorization is one of many routes to connect users and permissions in order to authorize particular permissions to certain users through their roles. Not every security framework supports this 3-step authorization connection. For example, Java EE only have User-Role authorization. Thus, all the functionalists are statically bonded to the particular roles in the code. Whereas, URP can be dynamic. By assigning permissions to the method level, any privileged users can maintain Role-Permission relationship without changing the existing code.

Security Realm

A Security Realm is a mechanism to protect the resources of your application. In Winter Security, system can retain user credentials, roles, and permissions from a particular realm. It connects to an authentication and authorization information provider, such as a database or file system. By default, Winter Security uses a JdbcRealm to connect database. You can write your own Realm by implementing the Realm interface.

Customizable Handlers

Customizable Handlers are the ways to define certain actions during an authentication and authorization process. There are 3 types of Handlers in Winter Security: AuthenticationContextHandler (AECH), AuthenticationExceptionHandler (AEEH), and AuthorizationExceptionHandler (AOEH). AECH collects user credentials of an incoming request. AEEH tells what to do if a user is not authenticated. AOEH tells what to do if a user attempts to access non-permitted method.

Authentication and authorization workflow

A typical workflow of an authentication and authorization process starts at collecting user credentials using AECH. The user credentials then being stored in an AuthenticationContext**. Once the request hits a method that requires certain permission, an AuthorizationInterceptor will exam the user credentials in AuthenticationContext with user information provided by the Security Realm. If everything is OK, the user then is permitted to access the method. Otherwise, depending on what problems are, AEEH or AOEH will be called to handle the situations.

Install Winter Security for your project

In order to use Winter Security, you need to build your project with related libraries including Winter Core and Winter Security. There are 2 ways of doing this:
1. Download .jar files and include them into your project’s build path: winter-core, winter-security.
2. Use Maven build tool to declare Winter Security dependency* in the pom.xml file:

<project>
    ...
    <dependencies>
        ...
        <dependency>
            <groupId>ca.ljz</groupId>
            <artifactId>winter-security</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        ...
    </dependencies>
    ...
</project>

Once you done one of the above options, Winter Security will be activated for your project right away.

Configurations

Winter Security follows an idea of convention over configuration to minimize configurations setting. However, you still have to have a configuration file and at least point out which data source to be used to retrieve user information.
Once you have Winter Security installed on your project, it is activated. If you run your project right away, you will get an error saying there is no data source connected. That is exact what we should get. Winter Security by default uses a JdbcRealm to retrieve user information from a database. You could either write your own Realm by implementing Realm interface, or indicate a data source in the configuration file. You can explore more about writing a Realm in the Java Doc. Instead of writing one, I am going to talk more about configurations with the default JdbcRealm.

application.properties

In order to configure Winter Security, you need to create a text file named application.properties in your default package (known as default directory of the project classloader). If you don’t know where default package is, just create a new class in your IDE with empty package entry. The new class will be created in the default package of your project. That folder is where to store your application.properties file.
The configuration file, application.properties, is a key-value paired text file to be loaded by java.util.Properties. Thus, it should follow the standard format of key-value property file. In Winter sample project, you can find all predefined keys and their default values in the configuration file as an example.

DataSource property

To specify a data source, you need to assign the JNDI name of the data source to “DataSource” key/property, e.g. DataSource=jdbc/sample. The JNDI name should have been predefined in your application server.
You don’t need other lines in application.properties file unless you want to customize other properties. Now, you have had one line key-value pair of DataSource property, your project should be able to start again normally.

Conventions for table structure

In previous sections, we talked about URP (User-Role-Permission) authorization. To support this feature, the database tables should be created following this structure. As a suggestion, 5 tables would be involved in authentication and authorization progress: user, user_role, role, role_permission, permission. From the table naming convention, you would know that user_role and role_permission are bridging tables for many-to-many relationships between user, role, and permission tables.
To use the default JdbcRealm, you should either have exact same naming for tables and columns to match the predefined SQL queries, or, you can specify queries in the configuration file.
To specify queries, you need define values for 3 keys/properties in application.properties file: Query.Password, Query.Role, and Query.Permission.

Query.Password property

You need a sql query that takes a username to get the associated password. E.g. Query.Password=select password from user where username = ?

Query.Role property

This property demands a username and returns a set of roles. E.g. Query.Role=select role from user_role where username = ?

Query.Permission property

By searching across user_role and role_permission tables, this query is to find all permissions of a given user. E.g. Query.Permission=select permission from user_role ur, role_permission rp where ur.role = pr.role and ur.username = ?
Depending on your actual table naming and structure, the queries you have can be different. But, the idea is same: use a given username to query whatever the system needs.

Method level security

Once finishing above settings, you can start using Winter Security to secure your program. Winter Security really emphasizes method level security. In a brief, you should have all your sensitive methods being registered to related permissions, and let the security framework check each method call to see if the required permission is granted to the caller/user who makes that call. In other words, all you need to do is to register a permission to each method. The way of doing that is to annotate the method with @PermissionCheck annotation.

Authenticate user

@PermissionCheck is an annotation defined by Winter Security. By barely placing this annotation on a method, the framework will do authentication check, and all authenticated users will be allowed to call the method.

Register method

To register a method, you just need to use this annotation on the method with a value, e.g. @PermissionCheck(“getAllUsers”) public Response getAll(){…}. The value “getAllUsers” is a permission name. It will be examed to match one of the permissions of the caller when the method is being called.

Non-protected method

If a method is not annotated with @PermissionCheck, it is not protected by Winter Security.

AuthenticationContext

One thing I would like to mention is the way to get caller’s information. Although, it is not implemented by Winter Framework, it is still good to know when using Winter Security.
Winter Security uses AuthenticationContext to store caller’s information of an incoming request, including name and password. Since Winter is built upon Java EE framework, it praises CDI to retreive AuthenticationContext. Thus, AuthenticationContext can be injected in any managed beans. In your code, simply make a field of @Inject AuthenticationContext, then you can get the caller’s name from it by calling getName() method.

Conclusion

After reading this blog, you should be able to setup and use Winter Security to secure your project. You may explore more about this framework when you atually use it in your project. If you really want to take a deeper look into Winter Project, you can check its GitHub repository. I hope you enjoy it.

* Because Winter Framework has not been submitted to Maven Central repository, the current version has to be installed to your local machine. However, when generating distributable .war file, you can choose to pack the dependencies to avoid dependency missing problems.
** AuthenticationContext is a class containing caller’s username and password of current request.

This blog may not be up to date. Please see the original post from Blogger http://ift.tt/2lHwDmt
via IFTTT.

Overview of Winter Framework

Winter project is an open source project using Apache License
Version 2.0. It started in the Winter 2017, which was where its name came from.
Winter Framework intended to make life easier for Java Web Development with
Java EE environment. It helps developers to simplify common tasks such as
Security and Persistence in an efficient, easy, and best possible ways while
developing applications.

The roadmap of the Winter framework includes 5 major parts:
1. Winter Version Control: It can also be called Winter Parent,
which essentially a Maven POM project used as a parent project, which controls the
versions of dependencies that other Winter components use. It is important to
make sure each module uses the same versions of dependencies so that there is
no conflict between each other.
2. Winter Core: Winter uses CDI API (JSR 299: Contexts and
Dependency Injection for the JavaTM EE platform) as its default context and
dependency, which means it typically needs to run with an application server,
e.g. GlassFish, WildFly, etc. However, it has a light weight property file
injection component which is called Winter Core. Other Winter components depend
on it, and use it to inject properties and objects specified in the property
files.
3. Winter Security: Winter Security is the first up and running
component has been developed for people to use. The main difference between
Java EE security framework and Winter Security is the idea behind authorization
control. Java EE security framework primarily is a role based authorization
system. Methods or APIs are assigned to roles, and users who has the roles will
be authorized. There is nothing wrong about this mechanism, but it is not
natural. In other words, system does not know the workflows. It only knows when
to let pass or stop. Winter Security marks workflow on method level. Instead of
using configurational nor programmatical ways to control the authorization
process, developers can hand out the authorization to the business side, and
let whoever knows the business to take control of it.
4. Winter Data API: Winter Data API will be the next major
component to be developed per the roadmap. Inspired by Spring Data Framework, Winter
Data API will be similar but less complex. The target is to provide an easy to
use API which wraps JPA for developers to avoid boilerplate code for common
CRUD tasks.
5. Winter Common Utils: As in daily development, we always
have small utils that are necessary but does not come with standard libraries.
With Winter Core empowered, these utils now can be easier to use and
configurable.

So, if you are interested in this project, you can download
it on http://ift.tt/2k8v56X.
While I am writing this article, the current version of Winter Framework is 0.0.1-SNAPSHOT,
which means it is still under development. Even though, it is a fast-growing
project worth to give a try. Also, because it is open source, anyone can
download the code and contribute to it. This project is being managed as most
open source projects. To make your contributions, simply pick up an issue on its
GitHub repository and fix it, then make a pull request to submit your code. If
you find any bugs, you can also create an issue. If you know how to fix it, you
can fix it by yourself. Otherwise, leave the issue open to let other developers
fixing it.

This blog may not be up to date. Please see the original post from Blogger http://ift.tt/2kprJK6
via IFTTT.

Develop AspectJ Library

AspectJ is an aspect-oriented programming (AOP) extension created at PARC for the Java programming language. – Wikipedia

In fact, things like Servlet Filters, EJB interceptors, or even database triggers are all sharing the concept of AOP. This article will focus on AspectJ in particular. Personally, I feel AspectJ gives a every different view on how software can be written. A weird thing that I found was most AspectJ related documentations were quite old. But, since it’s popular in many mordern frameworks such as Spring, I guess it’s worth to learn.

How is an AspectJ project used by other projects as a library?

To develop an AspectJ project and make other projects to use it, you have to know how the aspects are applied to the targeted components. AspectJ uses bytecode manipulation mechanism to intervene certain life cycle events of java classes at compile time. Because of that, it wouldn’t work if an AspectJ project is just being imported normally. Instead, it must be picked up at compile time to manipulate the bytecode when the targeted classes are generated. In fact, AspectJ has its own compiler, which could either be used standalone or work together with your chosen javac for jdk version control purposes.
To prepare for the practice in the rest sections, you need to have AspectJ Development Tools (AJDT) installed on your Eclipse. Although, I’ll introduce based on Eclipse, you can also develop AspectJ project with Intellij and NetBeans.

Eclipse plugin

AJDT is an eclipse plugin. You can find multiple versions of it. The latest one is 4.6 (copy the url as an Eclipse repository to install).

Intellij setup

You can find an introduction of how to set up your Intellij to work with AspectJ.

NetBeans plugin

There is a third party plugin called AspectJ-for-NetBeans developed quite a while ago (I heard it was developed by one person, which is very impresive).

Build an AspectJ project

There are various ways to create an AspectJ project: you can simply create an AspectJ project from scratch; you can have an existing Java project to convert to an AspectJ project. The way I’m going to do it is to create a Maven AspectJ project. By doing so, I would be able to just install my project to a local or remote repository. When it turns to that other project needs to import this AspectJ project, it can be done by just configuring the Maven configurations.

Create a Maven AspectJ project

A Maven AspectJ project is a maven project with a few AspectJ related configurations to assist while going through compile phase. Therefore, a simple Maven project is good to go for this practice.
Here is the initial pom.xml file I have (really nothing more than a simple initial pom file):
<project xmlns="http://ift.tt/IH78KX"
    xmlns:xsi="http://ift.tt/ra1lAU"
    xsi:schemaLocation="http://ift.tt/IH78KX http://ift.tt/VE5zRx">
    <modelVersion>4.0.0</modelVersion>
    <groupId>ca.ljz</groupId>
    <artifactId>special-logger</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</project>
By default, this project would not compile with AspectJ. To do that, we need to add:
  1. aspectj-maven-plugin
  2. aspectjrt (AspectJ run time dependency)
Optional: properties are optional. I added the above plugins and dependencies in <pluginManagement> and <dependencyManagement> first, which can be added to <plugins> and <dependencies> directly.
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.source-target.version>1.8</java.source-target.version>
    <aspectj.version>1.8.7</aspectj.version>
</properties>
<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>${java.source-target.version}</source>
                    <target>${java.source-target.version}</target>
                    <!-- IMPORTANT -->
                    <useIncrementalCompilation>false</useIncrementalCompilation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.7</version>
                <configuration>
                    <!-- OPTIONAL
                    <showWeaveInfo>true</showWeaveInfo>
                    -->
                    <source>${java.source-target.version}</source>
                    <target>${java.source-target.version}</target>
                    <Xlint>ignore</Xlint>
                    <complianceLevel>${java.source-target.version}</complianceLevel>
                    <encoding>${project.build.sourceEncoding}</encoding>
                    <!-- OPTIONAL
                    <verbose>true</verbose>
                    -->
                    <!-- OPTIONAL
                    <warn>
                        constructorName,
                        packageDefaultMethod,
                        deprecation,
                        maskedCatchBlocks,
                        unusedLocals,
                        unusedArguments,
                        unusedImport
                    </warn>
                    -->
                </configuration>
                <executions>
                    <execution>
                        <!-- IMPORTANT -->
                        <phase>process-sources</phase>
                        <goals>
                            <goal>compile</goal>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </pluginManagement>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
        </plugin>
        <!-- OPTIONAL
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
        </plugin>
        -->
    </plugins>
</build>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
    </dependency>
</dependencies>
The Maven AspectJ project now is created. As we mentioned above, the project needs to be compiled with either ajc (AspectJ compiler) or both ajc and javac. Please refer to the comments in the above pom settings to figure out how to do it in either way.

Create an annotation (optional)

Creating an annotation is not a must. But since it’s a common practice, I just want to show how to work with annotations in AspectJ. So, create an annotation first. It can be something like this:

package ca.ljz.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(java.lang.annotation.ElementType.METHOD)
public @interface Log{
    String prefix() default "";
}

The purpose of this annotation is to let user place it on a specific method to log. It doesn’t sound like how most loggers work, but it’s good for this example.
Other than using an annotation, AspectJ can also catch a predefined signature pattern, e.g. a method signature pattern such as set* or get* etc. But, when programming a library, it’s very unlikely to use pattern matches in most case. The exceptions are setters and getters, etc.

Create an aspect

In AspectJ, an aspect is a special entity contains the descriptions of when and how to deal with life cycle events of targeted java classes. The following code stub describes a log aspect for what we are doing:

package ca.ljz.aspects;

import ca.ljz.annotations.Log;
import org.aspectj.lang.reflect.MethodSignature;

public aspect LogAspect {

    pointcut log() : execution(* *(..)) && @annotation(Log);

    before() : log() {
        System.out.println("enter "
            + ((MethodSignature) thisJoinPoint.getSignature()).
                getMethod().getAnnotation(Log.class).prefix()
            + thisJoinPoint.getSignature());
    }

    after() : log() {
        System.out.println("exit "
            + ((MethodSignature) thisJoinPoint.getSignature()).
                getMethod().getAnnotation(Log.class).prefix()
            + thisJoinPoint.getSignature());
    }
}
Here is a list of the meanings of each part of the pointcut declaration.

  • log(): the identifier of this pointcut, which can be referred in advices
  • execution: the action of the target to be intercepted
  • 1st *: this star indicate that the return type can be anything
  • 2nd *: this is the name pattern of methods, which in this case, means any name
  • (..): this refers to the parameter pattern, which in this case, means any parameter(s)
  • &&: this is an logic operator, which indicates both sides condition must satisfied
  • @annotation(Log): this means that there must be a Log annotation

before() and after() are the time points to indicate when the advice should be executed.
To know more about AspectJ syntax, here are some useful links:

Install the library

There are several types of places you can install your library. Just to keep things as simple as possible, I’m just going to run a built-in maven phase: install. You can easily find it by right click on the project, and it’s in Run As sub menu.

Import an AspectJ project

Like building an AspectJ project, to import an AspectJ project also requires to add/change to the AspectJ compiler. Depending on how you build your project, there are different ways to accomplish this.

Non-maven project

For a non-maven project, you need to:

  1. Convert the Java project to AspectJ project (right click project -> configure);
  2. Add the library into Project Build
  3. Add the library into AspectJ Build Inpath (project properties -> AspectJ Build);

Maven project

For a maven project, you need to:

  1. Configure the project into a Maven AspectJ project (see Create a Maven AspectJ project section);
  2. Add the library as a dependency;
  3. Add the library as an <aspectLibrary> into <configuration> in aspectj-maven-plugin
To add the library into aspectj-maven-plugin <configuration>, it needs to include <groupId> and <artifactId>. The aspect library is something like this:

<aspectLibraries>
    <aspectLibrary>
        <groupId>ca.ljz</groupId>
        <artifactId>special-logger</artifactId>
    </aspectLibrary>
</aspectLibraries>

In particular, to use this library, you just need to add @Log on any method. The project to import AspectJ library project can be either a jar or a war project.

This blog may not be up to date. Please see the original post from Blogger http://ift.tt/2i8nNMm
via IFTTT.