Saturday, July 23, 2016

Springframework 1 - How to unify springframework JARs' version in your project?

It is possible to accidentally mix different versions of spring JARs when using maven. For example, you may find that a third-party library, or another spring project, pulls in a transitive dependency to an older release. If you forget to explicitly declare a direct dependency yourself, all sorts of unexpected issues can arise.

To overcome such problems maven supports the concept a "Bill of Materials" dependency or "BOM" dependency. You can import the spring-framework-pom in your dependencyManagement section to ensure that all spring dependencies (both direct and transitive) are at the same version.
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-framework-bom</artifactId>
            <version>4.3.1.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

After using this BOM you can find a spring-framework-bom-4.3.1.RELEASE.pom inside directory, .m2/repository/org/springframework/spring-framework-bom/4.3.1.RELEASE. This file contains all springframework components of this version.

What does 'import' scope of dependency tag mean?
  • import (only available in Maven 2.0.9 or later)
    This scope is only used on a dependency of type pom in the <dependencyManagement> section. It indicates that the specified POM should be replaced with the dependencies in that POM's <dependencyManagement> section. Since they are replaced, dependencies with a scope of import do not actually participate in limiting the transitivity of a dependency.

You can add this BOM into parent pom to unify all sub-projects. I added it for my project I'm creating for fun.

<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.martian.apps.springlab</groupId>
    <artifactId>parent</artifactId>
    <packaging>pom</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>parent</name>
    <description>Springframework Laboratory :: parent pom</description>

    <modules></modules>

    <properties>
        <springframework.version>4.3.1.RELEASE</springframework.version>
        <slf4j.version>1.7.12</slf4j.version>
        <log4j.version>1.2.17</log4j.version>
        <junit.version>4.12</junit.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- servlet -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>2.5</version>
                <scope>provided</scope>
            </dependency>
            <!-- jstl -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <version>1.2</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-framework-bom</artifactId>
                <version>${springframework.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>


            <!-- log -->
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>1.2</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>jcl-over-slf4j</artifactId>
                <version>${slf4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>jul-to-slf4j</artifactId>
                <version>${slf4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>log4j-over-slf4j</artifactId>
                <version>${slf4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>${slf4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>${slf4j.version}</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>apache-log4j-extras</artifactId>
                <version>${log4j.version}</version>
            </dependency>
           
           
            <!-- junit -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
   
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project> 

Saturday, December 19, 2015

Spring MVC Implements RESTful

Implements following requirement:

  1. Using maven to manage project 
  2. Spring mvc as main architecture
  3. Annotation configuration
  4. Using JSON request response and java object auto converting

1. Dependencies and pom

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <slf4j.version>1.7.12</slf4j.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-framework-bom</artifactId>
                <version>4.1.7.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!-- javaee -->
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- jstl -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
            <scope>provided</scope>
        </dependency>
     
        <!-- springframework core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
        </dependency>
     
        <!-- springframework web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
     
        <!-- json bind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.6.4</version>
        </dependency>
     
        <!-- Log -->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>${slf4j.version}</version>
        </dependency>  
    </dependencies>

2. web.xml

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/webContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>

3. webContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans     
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://www.springframework.org/schema/mvc
                           http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
                           http://www.springframework.org/schema/context 
                           http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:component-scan base-package="com.gemalto.offerflex" />
    <mvc:annotation-driven />
    <context:annotation-config/>
    
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    
    <!-- Configure to plugin JSON as request and response in method handler -->
    <bean  class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="jsonMessageConverter"/>
            </list>
        </property>
    </bean>
    
    <bean id="jsonMessageConverter"
               class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
</beans>

4. VO

JSON format message in request body will be parsed to VO.
VO will be convert to JSON message and written into response body.

public class House {
    private String address;
    private int roomNum;

    public String getAddress() {
        return address;
    }

    public int getRoomNum() {
        return roomNum;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public void setRoomNum(int roomNum) {
        this.roomNum = roomNum;
    }
}


public class Person {
    
    private String id;
    private String name;
    private List<House> houses;
    
    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }
    
    public List<House> getHouses(){
        return houses;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public void setHouses(List<House> houses){
        this.houses = houses;
    }
     
}

5. Controller

@RestController
@RequestMapping ("/rest")
public class TestRestController {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(TestRestController.class);
    
    /**
     * http://localhost:7001/WebTest/rest/params.action?id=10&name=wang bo
     */
    @RequestMapping(value="/params", method=RequestMethod.GET)
    @ResponseStatus(value=HttpStatus.OK)
    public String params(@RequestParam String id, @RequestParam String name){
        
        LOGGER.info("params...");
        LOGGER.info("id  : " + id);
        LOGGER.info("name: " + name);
        
        return "Received!";
    }
    
    /**
     * http://localhost:7001/WebTest/rest/pathVariable/10/Tom.action
     */
    @RequestMapping(value="/pathVariable/{id}/{name}", method=RequestMethod.GET)
    @ResponseStatus(value=HttpStatus.OK)
    public String pathVariable(@PathVariable String id, @PathVariable String name){
        
        LOGGER.info("pathVariable...");
        LOGGER.info("id  : " + id);
        LOGGER.info("name: " + name);
        
        return "Received!";
    }
    
    /**
     * Json object, Person, does not implements Serializable interface and does not need any constructor.
     * 
     */
    @RequestMapping(value="/jsonObj", method=RequestMethod.POST)
    @ResponseStatus(value=HttpStatus.OK)
    public Person jsonObj(@RequestBody Person person){
        return dealWith(person);
    }
    
    private Person dealWith(Person person){
        LOGGER.info("jsonObj...");
        LOGGER.info("id  : " + person.getId());
        LOGGER.info("name: " + person.getName());
        
        if(person.getHouses() != null){
            for(House house : person.getHouses()){
                LOGGER.info("houses --- " + house.getAddress() + ", " + house.getRoomNum());
            }
        }else{
            LOGGER.info("houses --- null");
        }
        
        return person;
    }
    
}

6. Difference between @RestController and @Controller

They have no difference essentially. @RestController equals to @Controller plus @ResponseBody.

Thursday, June 5, 2014

Several ways to manage windows on OS X

1. Switch between different active windows of same application
Command-` (grave accent)

2. Minimize current window
Command-M

3. Enter and exit full screen
Command-Control-F

4. Close window
Command-W
or
Command-Q (always really quit application except Finder)

5. Hide other applications' window and keep focus window
Command-Option-H

6. Hide focus window
Command-H

7. Switch between different windows
Four fingers slide from bottom to top on touchpad and select the one you need.

How to cut and paste file or folder by shortcut on OS X?

Heard this operation is disabled on OS X. But we have another option, copy first then paste and delete.

1. Command + C
2. Command + Option + V

Wednesday, June 4, 2014

Set JAVA_HOME on OS X

Add on line in  ~/.profile


export JAVA_HOME=$(/usr/libexec/java_home)

Save and quit.

** "/usr/libexec/java_home" points to Java home which is being used now if there are multiple JDKs installed.

Eclipse can't open on OS X

Double-click eclipse icon but it is prohibited.
Because it's limited by Security & Privacy in System Preference. Select to use: Anywhere on Allow apps downloaded from.

Tuesday, June 3, 2014

Install JDK on OS X 10.9.3 (or above?)

1. Go to oracle web site to download the OS X dedicated installer, e.g. jdk-7u60-macosx-x64.dmg.
2. Double click and follow the prompts to install.

Note: There is one point needs to clarify. Some posts and oracle official installation instructions mentions you need to go to Applications -> Utilities -> Java Preferences and do certain operations. It seems no need do anything on it now because JDK is not pre-installed on OS X 10.9.x or above anymore, and you even can't find Java Preference in Utilities folder. The Java control panel is now at System Preference.

Open terminal and type java -version
...Now can start working.