Monday, September 16, 2013

Hibernate one-to-many with child entity using composite primary key

Scenario: A customer can have multiple orders. The customer entity has cid as primary key, the order has composite primary key (order_id + cid)

Database tables:

 CREATE TABLE customers (
    cid VARCHAR(8) PRIMARY KEY,
    name VARCHAR(255)
 );

 CREATE TABLE orders (
    order_id INT,
    customer_id VARCHAR(8),
    amount REAL,
    PRIMARY KEY(order_id, customer_id),
    FOREIGN KEY(customer_id) REFERENCES customers(cid)
 );

The Java code using Hibernate ORM will be

Customer.java

@Entity
@Table(name="customers")
public class Customer implements Serializable {
    @Id
    @Column(name="cid")
    private String customerId;

    @OneToMany(fetch=FetchType.EAGER, mappedBy="orderRecordPK.customer")
    @Cascade(CascadeType.ALL)
    private Set<OrderRecord> orderRecords = new HashSet<OrderRecord>();

    ...
    constructor, other fields, getters and setters
}    

OrderRecord.java

@Entity
@Table(name="orders")
public class Order implements Serializable {
    @EmbeddedId
    private OrderRecordPK orderRecordPK;

    ...
    constructor, other fields, getters and setters
}

OrderRecordPK.java

@Embeddable
public class OrderRecordPK implements Serializable{
    @Column(name="order_id")
    private int orderId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="customer_id", nullable=false)
    private Customer customer;

    ...
    constructor, other fields, getters and setters
}


Hibernate one-to-many with child entity using id as primary key

Scenario: A customer can have multiple phones. The customer entity has cid as primary key, and the phone has phone_id as primary key

Database tables:

 CREATE TABLE customers (
    cid VARCHAR(8) PRIMARY KEY,
    name VARCHAR(255)
 );

 CREATE TABLE phones (
    phone_id INT PRIMARY KEY,
    customer_id VARCHAR(8),
    number INT,
    FOREIGN KEY(customer_id) REFERENCES customers(cid)
 );

The Java code using Hibernate ORM will be

Customer.java

@Entity
@Table(name="customers")
public class Customer implements Serializable {
    @Id
    @Column(name="cid")
    private String customerId;

    @OneToMany(fetch=FetchType.EAGER, mappedBy="customer")
    @Cascade(CascadeType.ALL)
    private Set<OrderRecord> phones = new HashSet<OrderRecord>();

    ...
    constructor, other fields, getters and setters
}    

Phone.java

@Entity
@Table(name="phones")
public class Phone implements Serializable {
    @Id
    @Column(name="phone_id")
    private int phoneId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="customer_id", nullable=false)
    private Customer customer;

    ...
    constructor, other fields, getters and setters
}

Next, Hibernate one-to-many with child entity using composite primary key


Thursday, August 1, 2013

Java class with generic type

Generic type T specifies the type of the object that will be handled in a class.
The advantage of using generic type is the object type is checked in compile time. A class that is designed to handle object with type A will not be mistakenly passed an object with Type B

Suppose we define a Container to store and retrieve an object. In order to know what type of object we will put later, we add type parameter T.
public interface Container<T> {
 public void set(T t);
 public T get();
}

and we have fruits Apple and Orange that will be put the in container
public class Apple {

 private String label;

 public Apple(String label) {
  super();
  this.label = label;
 }
 
 @Override
 public String toString() {
  return "Apple [label=" + label + "]";
 }

}

public class Orange {

 private String label;

 public Orange(String label) {
  super();
  this.label = label;
 }

 @Override
 public String toString() {
  return "Orange [label=" + label + "]";
 }

}

A box that implements Container will be used to put Apple or Orange
public class Box implements Container<T> {

 private T t;
 
 public void set(T t) {
  this.t = t;
 }
 public T get() {
  return t;
 }

}

To create a box that can have Apple only
Box<Apple> genericAppleBox = new Box<Apple>();

A box that can have Orange only
Box<Orange> genericOrangeBox = new Box<Orange>();

If we try to put an Orange in the apple box,
genericAppleBox.set(orange);

the compiler will complain, "The method set(Apple) in the type Box is not applicable for the arguments (Orange)"

The type parameter also can be specified in the class definition
To declare a box class that will store Apple only
public class AppleBox implements Container<Apple> {

 private Apple apple;

 public Apple get() {
  return apple;
 }

 public void set(Apple apple) {
  this.apple = apple;
 }
 
}

A box will will store Orange only
public class OrangeBox implements Container<Orange> {

 private Orange orange;

 public Orange get() {
  return orange;
 }

 public void set(Orange orange) {
  this.orange = orange;
 }

}

To create the box for Apple only
AppleBox specificAppleBox = new AppleBox();

To create the box for Orange only
OrangeBox specificOrangeBox = new OrangeBox();

If we try to put an Orange to the Apple box,
specificAppleBox.set(orange);

the compiler will complain, "The method set(Apple) in the type AppleBox is not applicable for the arguments (Orange)"

Reference
http://docs.oracle.com/javase/tutorial/java/generics/

Thursday, July 25, 2013

Hibernate cascade error, Type mismatch: cannot convert from CascadeType to CascadeType[]

One day when I tried to use the Hibernate @Cascade annotation, the syntax was correct, but I had the error of "Type mismatch: cannot convert from CascadeType to CascadeType[]".

It turned out I had a mismatch import. To fix it, remove the line

        import javax.persistence.CascadeType;

then add the line

        import org.hibernate.annotations.CascadeType;

Reference
JPA & Hibernate annotation common mistake
http://www.mkyong.com/hibernate/cascade-jpa-hibernate-annotation-common-mistake/

Thursday, July 11, 2013

Test Spring security protected web app using curl

Form-based authentication
1. Obtain a session and write it to the file. Note that the spring security path j_spring_security_check is used for this step
$ curl --data "j_username=myname&j_password=mypswd" http://localhost:8080/SpringSecurityAuth/j_spring_security_check --cookie-jar cookies.txt

2. Access the protected URL with the session
$ curl http://localhost:8080/SpringSecurityAuth/api/helloworld --cookie cookies.txt

HTTP basic authentication

Option 1

Send username and password for each request
$ curl --user myname:mypwsd http://localhost:8080/SpringSecurityAuth/api/helloworld

Option 2

1. Obrain a session similar to the way in form-based authentication, but using spring security path j_spring_security_check is not needed
$ curl --user byname:mypwsd http://localhost:8080/SpringSecurityAuth/api/helloworld --cookie-jar cookies.txt

2. Access the protected URL with the session
$ curl http://localhost:8080/SpringSecurityAuth/api/helloworld --cookie cookies.txt

Simple REST Stateless configuration
To achieve REST stateless feature, the element in security configuration file can be configured as follow
  <!-- Stateless RESTful service using Basic authentication -->
  <http pattern="/restful/**" create-session="stateless">
      <intercept-url pattern='/**' access='ROLE_REMOTE' />
      <http-basic />
  </http>
Then the saved session will not work and providing username and password is required for each request.

This feature can be achieved only with HTTP basic authentication because the form-based authentication needs to have a session to access the protected resource, but the session is not valid here.

This approach may not be secure enough because the username and password are transmitted in each request. To have a more secure implementation, using option to generate token and customer-filter to authenticate token may be required (authentication could be form-based or HTTP basic since token is being used).


Reference
Interact with a spring-security protected application
https://bowerstudios.com/node/913

Spring Security Basic Authentication
http://www.baeldung.com/spring-security-basic-authentication

Advanced Namespace Configuration
http://static.springsource.org/spring-security/site/docs/3.1.x/reference/security-filter-chain.html#filter-chains-with-ns

Friday, May 17, 2013

Use Apache Maven to create Java projects

Why should I use Apache Maven to create a Java project?

If the Java project will not use external dependencies (some jar files such as junit, mysql-connector-java), then there is no need to use Maven. But when using external jars are needed, Maven will make life much simpler.

Maven maintains a list of commonly used dependencies in its repository. To include the dependencies in the project, simply add the dependency entries to pom.xml. When Maven generates a project, it reads pom.xml and will automatically download all the related jar files. Therefore, you do not have to search for the jar and install them one by one.

A tool that can find most current version and generate xml entry for pom.xml can be found here, http://mvnrepository.com

Next: Install Apache Maven on Windows

Sunday, May 12, 2013

Spring 3 Hello World

Create a Maven project, make the pom.xml as the sample code below and convert it to Eclipse importable by mvn eclipse:eclipse

<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.example.core</groupId>
  <artifactId>Spring3HelloWorld</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Spring3HelloWorld</name>
  <url>http://maven.apache.org</url>

  <properties>
    <org.springframework-version>3.2.2.RELEASE</org.springframework-version>
  </properties>

  <dependencies>
  
        <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>3.8.1</version>
                <scope>test</scope>
        </dependency>
 
 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>${org.springframework-version}</version>
 </dependency>
 
 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>${org.springframework-version}</version>
 </dependency>
 
  </dependencies>
</project>
 
After the project is imported into Eclipse, create a resources folder first. Select the project on Project Explorer, then go to Project -> Properties, then Add Folder...  

















Add the resource under <Project Name>/src/main

 
 
 
 
 
  
 
 
 
 
 
 
 
 
 
Add the AppBeans.xml with the sample code to <Project Name>/main/src/resources
 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
 <bean id="helloworldBean" class="com.example.core.HelloWorld">
  <property name="name" value="Spring 3" />
 </bean>
</beans> 
 
 
Add the HelloWorld.java to <Project Name>/main/src/java
 
package com.example.core;

public class HelloWorld {
 private String name;
 
 public void setName(String _name){
  this.name = _name;
 }
 
 public void sayHello(){
  System.out.println("Hello World, " + this.name + "!");
 }
}
 
Add the code to App.java
 
package com.example.core;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Hello world!
 *
 */
public class App {
    public static void main( String[] args ) {
     ApplicationContext context = new ClassPathXmlApplicationContext("AppBeans.xml");
     HelloWorld obj = (HelloWorld)context.getBean("helloworldBean");
     obj.sayHello();
    }
} 
 

The final file structure 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Select App.java and run as Java Application
Hello World, Spring 3!