Pages

Sunday, 5 May 2013

One to many with composite key

First our parent class looks like this:
1:  import javax.persistence.*;  
2:    
3:  @Entity  
4:  @Table(name="Parent")  
5:  public class Parent {  
6:     
7:   @EmbeddedId  
8:   private ParentPk parentPk = new ParentPk();  
9:     
10:   @Column(name="NormalField")  
11:   private String normalField;  
12:     
13:   public Parent(){}  
14:     
15:   public Parent(String field) {  
16:    this.normalField = field;  
17:   }  
18:     
19:   public ParentPk getParentPk() {  
20:    return parentPk;  
21:   }  
22:    
23:   public void setParentPk(ParentPk parentPk) {  
24:    this.parentPk = parentPk;  
25:   }  
26:    
27:   public String getNormalField(){  
28:        return normalField;  
29:   }  
30:    
31:   public void setNormalField(String field){  
32:        normalField = field;  
33:   }   
34:  }  
And key class for the parent:
1:  import java.io.Serializable;  
2:    
3:  import javax.persistence.Column;  
4:    
5:  public class ParentPk implements Serializable{  
6:    
7:   private static final long serialVersionUID = 2194116512563143369L;  
8:    
9:   @Column(name="FirstKey")  
10:   private int firstKey;  
11:     
12:   @Column(name="SecondKey")  
13:   private String secondKey;  
14:    
15:   public ParentPk(){}  
16:     
17:   public ParentPk(int firstKey, String secondKey, String area) {  
18:    this.firstKey = firstKey;  
19:    this.secondKey = secondKey;  
20:   }  
21:    
22:   public int getFirstKey() {  
23:    return firstKey;  
24:   }  
25:    
26:   public void setFirstKey(int firstKey) {  
27:    this.firstKey = firstKey;  
28:   }  
29:    
30:   public String getSecondKey() {  
31:    return secondKey;  
32:   }  
33:    
34:   public void setSecondKey(String secondKey) {  
35:    this.secondKey = secondKey;  
36:   }  
37:     
38:  }  
And the child class:
1:  @Entity  
2:  @Table(name="Child")  
3:  public class Child{  
4:    
5:   @Id  
6:   @Column(name="Id")  
7:   private int id;       
8:    
9:   @Column(name="ChildField")  
10:   private String childField;  
11:     
12:   @Column(name="FirstKey",insertable=false,updatable=false)  
13:   private int firstKey;  
14:     
15:   @Column(name="SecondKey",insertable=false,updatable=false)  
16:   private String secondKey;  
17:    
18:   public int getId() {  
19:    return id;  
20:   }  
21:    
22:   public void setId(int id) {  
23:    this.id = id;  
24:   }  
25:     
26:   public String getChildField() {  
27:    return childField;  
28:   }  
29:    
30:   public void setChildField(String childField) {  
31:    this.childField = childField;  
32:   }  
33:     
34:   public int getFirstKey() {  
35:    return firstKey;  
36:   }  
37:    
38:   public void setFirstKey(int firstKey) {  
39:    this.firstKey = firstKey;  
40:   }  
41:    
42:   public String getSecondKey() {  
43:    return secondKey;  
44:   }  
45:    
46:   public void setSecondKey(String secondKey) {  
47:    this.secondKey = secondKey;  
48:   }  
49:    
50:   public Parent getParent() {  
51:    return parent;  
52:   }  
53:    
54:   public void setParent(Parent parent) {  
55:    this.parent = parent;  
56:   }  
57:    
58:   @ManyToOne  
59:   @JoinColumns({  
60:    @JoinColumn(name="FirstKey",referencedColumnName="FirstKey"),  
61:    @JoinColumn(name="SecondKey",referencedColumnName="SecondKey")  
62:   })  
63:   Parent parent;  
64:  }  

Web services in Spring 3.0 with JAX-WS

There is some information on the net about how to integrate Spring with JAX-WS but most of the stuff I've found has been using Spring 2.0. This will show you how to achieve web service integration with full wsdl generation in Spring 3.0 which is rather easy actually.
 
Below is the web.xml:

The applicationContext.xml is as follows:


The the essential part of this is really line 14 that does all the magic and the component scanning context xml declaration above that part. As the simpleJaxWsServiceExporter will essentially look thru any beans that have been declared that are decorated with the WebService attribute are create an endpoint for them like the example below:


1:  package com.dmcliver.springhibernatejaxws.endpoints;  
2:    
3:  import java.util.List;  
4:    
5:  import javax.jws.WebMethod;  
6:  import javax.jws.WebService;  
7:    
8:  import org.springframework.beans.factory.annotation.Autowired;  
9:  import org.springframework.stereotype.Service;  
10:  import com.dmcliver.springhibernatejaxws.domain.Person;  
11:  import com.dmcliver.springhibernatejaxws.domain.Profession;  
12:  import com.dmcliver.springhibernatejaxws.services.PersonService;  
13:    
14:  // This will be the port name appended with the word port at the end of the name  
15:  @Service("PersonServiceEndpoint")  
16:  // This will be the service name  
17:  @WebService(serviceName="PersonService")  
18:  public class PersonServiceEndpoint{  
19:    
20:       @Autowired  
21:        private PersonService personService;  
22:    
23:       @WebMethod  
24:       public List<Person> findByProfession(Profession profession){  
25:            return personService.findByProfession(profession);  
26:       }  
27:  }  
28:    

Since we've declared our spring context to enable component scanning we can now use this to our advantage to allow bean creation of a hibernate persistence layer as seen with the rest of xml in the application context file.

Note that this example is only valid for using in a non jee web container such as Tomcat or Jetty. If you are using a jee spec server then no applicationContext file is needed at all, you can simply declare the endpoint class in the web.xml file itself and there is a tutorial by Byron Kiourtzoglou over at java code geeks on this.

Full source is available at github

Tuesday, 23 April 2013

Spring validation and custom authentication with password salt

There's a lot of information out there about Spring when it comes to authentication, but a lot of it is either basic or incomplete. Especially when it comes to user account registration with advanced techniques such as custom authentication providers and password salts. 

So I decided to put a blog together to show how this can be achieved having had to figure this out and piece it together myself.

Firstly the spring-security.xml itself, notice the reference to application context config file at line 9. This is important to allow the spring container to inject the dependencies for the customerDao class.

1:  <?xml version="1.0" encoding="UTF-8"?>  
2:  <beans:beans xmlns:sec="http://www.springframework.org/schema/security"  
3:    xmlns:beans="http://www.springframework.org/schema/beans"  
4:    xmlns:p="http://www.springframework.org/schema/p"  
5:    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
6:    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
7:       http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">  
8:    
9:       <beans:import resource="servlet-context.xml"/>  
10:    
11:       <sec:http auto-config="true" use-expressions="true">  
12:            <sec:intercept-url pattern="/**" access="permitAll" />  
13:            <sec:form-login login-page="/login" default-target-url="/success" authentication-failure-url="/oops" />  
14:            <sec:logout logout-success-url="/logout" />  
15:       </sec:http>  
16:    
17:       <beans:bean id="customerDao" class="com.dmcliver.springvalidation.dataaccess.CustomerDaoImpl"></beans:bean>  
18:    
19:         <beans:bean id="userDetailsService" class="com.dmcliver.springvalidation.services.UserDetailsServiceImpl">  
20:              <beans:property name="customerDao" ref="customerDao"/>  
21:         </beans:bean>  
22:    
23:        <beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">  
24:          <beans:constructor-arg value="256"/>  
25:        </beans:bean>  
26:    
27:       <beans:bean id="saltSource"  
28:         class="org.springframework.security.authentication.dao.ReflectionSaltSource"  
29:         p:userPropertyToUse="username" />  
30:    
31:       <sec:authentication-manager alias="authenticationManager">  
32:      <sec:authentication-provider user-service-ref="userDetailsService">  
33:        <sec:password-encoder hash="sha" ref="passwordEncoder">  
34:          <sec:salt-source ref="saltSource"></sec:salt-source>  
35:        </sec:password-encoder>  
36:      </sec:authentication-provider>  
37:    </sec:authentication-manager>  
38:      
39:  </beans:beans>  
And what needs to be added to the web.xml:
1:       <context-param>  
2:            <param-name>contextConfigLocation</param-name>  
3:            <param-value>  
4:                 /WEB-INF/spring/root-context.xml,  
5:                 /WEB-INF/spring/appServlet/spring-security.xml  
6:            </param-value>  
7:       </context-param>  
8:         
9:       <filter>  
10:         <filter-name>springSecurityFilterChain</filter-name>  
11:         <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
12:       </filter>  
13:    
14:       <filter-mapping>  
15:         <filter-name>springSecurityFilterChain</filter-name>  
16:         <url-pattern>/*</url-pattern>  
17:       </filter-mapping>  
18:         
19:       <listener>  
20:            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
21:       </listener>  
The rest I probably wont bore you with as you can find it on the interwebz, however what I'll focus on is the registration part instead which is actually quite easy, all we need is a normal spring form and then the controller registration method will look something like this:
1:       @RequestMapping(value = "/register", method = RequestMethod.POST)  
2:       public String register(@Valid @ModelAttribute Customer customer, BindingResult result, Model model) {  
3:                        
4:            if(result.hasErrors()){  
5:                 return "register";  
6:            }       
7:            try{  
8:                 customerDao.save(customer);  
9:            }  
10:            catch(Exception ex){  
11:                 result.reject("gblErrMess",ex.getMessage());  
12:                 return "register";  
13:            }  
14:            model.addAttribute("userName",customer.getUserName());  
15:            return "success";  
16:       }  
With the customerDao save method as follows:
1:       @Transactional  
2:       public void save(Customer customer) {  
3:            String password = passwordEncoder.encodePassword(customer.getPassword(), customer.getUserName());  
4:            Session session = sessionFactory.getCurrentSession();  
5:            customer.setPassword(password);  
6:            session.save(customer);  
7:       }  
Thats about it really. You can find the entire project at github. I do apologise for the hastily written source code in the repo it is merely a proof of concept after all :)

References: 
http://www.mkyong.com/tutorials/spring-security-tutorials/
http://springinpractice.com/2008/10/11/hashing-and-salting-passwords-with-spring-security-2/