Category Archives for Spring

What does Spring DelegatingFilterProxy do?

What does Spring DelegatingFilterProxy do? I had never given it much thought about how Spring Security integrates with web.xml until I had to diagnose an issue involving the DelegatingFilterProxy and my Spring Security configuration.

Isle Of Harris

What does Spring DelegatingFilterProxy do?

I knew the starting point is the springSecurityFilterChain which uses the DelegatingFilterProxy, and this would instantiate the Spring Security filters according to my spring configuration –

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
    </filter-mapping

But what next?

DelegatingFilterProxy

A look at the javadoc for DelegatingFilterProxy states that –

Proxy for a standard Servlet Filter, delegating to a Spring-managed bean that implements the Filter interface

It further states that the filter-name corresponds to a bean in the Spring application context.

So in terms of Spring Security the DelegatingFilterProxy will look though the Spring Application Context for a bean “springSecurityFilterChain”. The only requirement for Delegated beans is that they must implement javax.servlet.Filter.

Initializing the springSecurityFilterChain

The springSecurityFilterChain is initialised in your spring configuration by, which will be passed to your DispatcherServlet –

<http ...> </http>

We can see this in action when we include code to add remove filters in Spring Security –

<http ...>
    ...        
    <custom-filter ref="mySecurityFilter" after="FORM_LOGIN_FILTER"  />
    ...
</http>

You can also see a list of filters created when you up spring security logging

What about Spring Boot?

Spring Security configuration for Spring Boot is simply a matter of adding a reference to “spring-boot-starter-security” to gradle or maven. We can then fine tune the security configurations through @EnableWebSecurity and overriding the configure method of a class extending WebSecurityConfigurerAdapter.

If we dig around under the hood we find that the DelegatingFilterProxy is still used. With the “springSecurityFilterChain” instantiated in SecurityFilterAutoConfiguration, which populates the DelegatingFilterProxyRegistrationBean with “springSecurityFilterChain” (AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) –

@Bean
@ConditionalOnBean(name = DEFAULT_FILTER_NAME)
public DelegatingFilterProxyRegistrationBean securityFilterChainRegistration(SecurityProperties securityProperties) {
    DelegatingFilterProxyRegistrationBean registration = new DelegatingFilterProxyRegistrationBean(DEFAULT_FILTER_NAME);
    registration.setOrder(securityProperties.getFilterOrder());
    registration.setDispatcherTypes(getDispatcherTypes(securityProperties));
    return registration;
}

Reference

http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#delegating-filter-proxy

https://spring.io/blog/2013/07/03/spring-security-java-config-preview-web-security/

http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#delegating-filter-proxy

Auto-generating Spring Security Tutorial – Custom JDBC Realms

This post builds on the set of spring-security posts I have done, and particularly my last post on Default JDBC Realms. The code is available on github, and spring-security-generator and the instructions to run the application are contained in the previous tutorial.

We also have a requirement to use a custom JDBC realm with the structure –

USER PASSWORD ROLES
customadmin customadmin ROLE_CUSTOM_ADMIN

Custom JDBC Tables

The tables Ive used in this example are renamed versions of the default tables -

create table custom_users (
  username varchar(256),
  password varchar(256),
  enabled boolean
);
create table custom_authorities (
  username varchar(256),
  authority varchar(256)
);
With inserts - 

insert into custom_users (username, password, enabled) values ('customadmin', 'customadmin', true);
insert into custom_authorities (username, authority) values ('customadmin', 'ROLE_CUSTOM_ADMIN');

Spring-Security-Generator

Using spring-security-generator we now select “JDBC Realm (Custom)” and supply the queries –

select username, password, enabled from custom_users where username = ?
select username, authority from custom_authorities where username = ?

The screen configuration is then –

screen-shot-2016-11-07-at-21-00-50

We then generate the code –

package com.glenware.springboot;

import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth)
            throws Exception {
         auth
             .jdbcAuthentication()
                 .dataSource(dataSource)
                   .usersByUsernameQuery(
                   "select username, password, enabled from custom_users where username = ?")
                   .authoritiesByUsernameQuery(
                   "select username, authority from custom_authorities where username = ?");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/webjars/**","/about.html","/rest/**").permitAll()
                .antMatchers("/admin/**").hasAnyRole("CUSTOM_ADMIN")
                .anyRequest().authenticated()
            .and()
                .formLogin()
                    .loginPage("/login")
                    .defaultSuccessUrl("/admin/admin.html")
                    .failureUrl("/login")
                    .permitAll()
             .and()
                .logout()
                    .logoutSuccessUrl("/")
                    .permitAll()
                    ;
    }
    
}

The key difference between this tutorial and the previous is that we supply the SQL directly to the usersByUsernameQuery and authoritiesByUsernameQuery

We can now copy this code to the parkrunpb applicaiton, and login using customadmin/customadmin

Auto-generating Spring Security Tutorial – Default JDBC Realms

The previous tutorial showed how we can auto-generate of spring security using a memory realm. This tutorial expands on this to cover Default JDBC Realms using the source code from the parkrunPB application

Security Requirements

The site has the following links and security requirements –

http://localhost:8080/ Accessible to all
http://localhost:8080/webjars Static Resources – Accessible to all
http://localhost:8080/about.html Static page – Accessible to all
http://localhost:8080/login.html Accessible to all
http://localhost:8080/admin/ Admin User
http://localhost:8080/rest Accessible to all

We also have a requirement to use a users and roles with the structure –

USER PASSWORD ROLES
admin admin ADMIN

Getting Started

The first thing we need to do is uncomment spring security in the maven pom –

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

We can then compile and run the code –

mvn spring-boot:run

The whole application is now locked down

Luckily we can login using the default username (user), and the password from the logs. Im my case –

2016-11-06 21:16:56.877 INFO 8088 --- [main] b.a.s.AuthenticationManagerConfiguration :
 Using default security password: e1c87658-8b7e-4b1e-88da-902b5356ef66

Default JDBC Tables

We can now begin to create our SecurityConfiguration using Spring Security Generator

screen-shot-2016-11-06-at-21-33-53

We then get the generated source code –

package com.glenware.springboot;

import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private DataSource dataSource;

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth)
			throws Exception {
         auth
             .jdbcAuthentication()
                 .dataSource(dataSource)
                     .withDefaultSchema()
				.withUser("admin").password("admin").roles("ADMIN");
	}

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/webjars/*","/about.html","/rest/**").permitAll()
                .antMatchers("/admin/**").hasAnyRole("ADMIN")
                .anyRequest().authenticated()
            .and()
                .formLogin()
                    .loginPage("/login")
                    .defaultSuccessUrl("/admin/admin.html")
                    .failureUrl("/login")
                    .permitAll()
             .and()
                .logout()
                    .logoutSuccessUrl("/")
                    .permitAll()
                    ;
	}

}

Key Points

  • Using JDBC Realm(Default) – The default realm means Spring Security will use its default users.ddl
  • Same configuration as before

We can now access the site the same as the memory realm, but with user details stored in the database. The next post will look at using a custom JDBC table

Apache CXF – JMS Spring Config

The JMS Spring Config Demo (samples\jms_spring_config) uses the wsdl_first code, and adds JMS transport through configuration

WSDL

The WSDL remains unchanged, with the port defined –

[sourcecode lang=”xml”] <wsdl:service name="CustomerServiceService">
<wsdl:port name="CustomerServicePort" binding="tns:CustomerServiceServiceSoapBinding">
<soap:address location="http://localhost:9090/CustomerServicePort"/>
</wsdl:port>
</wsdl:service>
[/sourcecode]

Spring Configuration

JMS is configured through the server-applicationContext.xml –

[sourcecode lang=”xml”] <bean id="jmsConnectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
</property>
</bean>

<bean id="jmsConfig" class="org.apache.cxf.transport.jms.JMSConfiguration"
p:connectionFactory-ref="jmsConnectionFactory"
p:targetDestination="test.queue"
/>

<!– JMS Endpoint –>
<jaxws:endpoint xmlns:customer="http://customerservice.example.com/"
id="CustomerServiceHTTP" address="jms://"
implementor="com.example.customerservice.server.CustomerServiceImpl">
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature" />
<bean class="org.apache.cxf.transport.jms.JMSConfigFeature" p:jmsConfig-ref="jmsConfig" />
</jaxws:features>
</jaxws:endpoint>
[/sourcecode]

There are 3 point of connectivity –

  • jmsConnectionFactory – Inject ActiveMQConnectionFactory into Spring’s JMS SingleConnectionFactory
  • jmsConfig – Inject the jmsConnectionFactory and queue name
  • jaxws:endpoint – Inject jmsConfig into the jaxws:endpoint

Apache CXF – JMS Queue

This sample(samples\java_first_jms) demonstrates how to connect to web services across JMS transport, instead of HTTP as in the previous examples.

Web Service Contract – jms_greeter.wsdl

  • <wsdl:operation name=”greetMe”>
  • <wsdl:operation name=”sayHi”>
  • <wsdl:operation name=”greetMeOneWay”>

The wsdl:binding contains the important information that this sample will operate on JMS –

  •  <soap:binding style=”document” transport=”http://cxf.apache.org/transports/jms”/>

Finally the wsdl:port definition defines the JMS Queue properties –

[sourcecode lang=”xml”] <wsdl:service name="JMSGreeterService">
<wsdl:port binding="tns:JMSGreeterPortBinding" name="GreeterPort">
<jms:address
destinationStyle="queue"
jndiConnectionFactoryName="ConnectionFactory"
jndiDestinationName="dynamicQueues/test.cxf.jmstransport.queue">
<jms:JMSNamingProperty name="java.naming.factory.initial" value="org.apache.activemq.jndi.ActiveMQInitialContextFactory"/>
<jms:JMSNamingProperty name="java.naming.provider.url" value="tcp://localhost:61616"/>
</jms:address>
<jms:clientConfig useConduitIdSelector="false"/>
</wsdl:port>
</wsdl:service>
[/sourcecode]

The implementation classes can be generated through the maven wsdl2java task.

Service Implementation

GreeterJMSImpl implements the JMSGreeterPortType interface –

[sourcecode lang=”java”] @javax.jws.WebService(portName = &amp;quot;GreeterPort&amp;quot;,
serviceName = &amp;quot;JMSGreeterService&amp;quot;,
targetNamespace = &amp;quot;http://cxf.apache.org/jms_greeter&amp;quot;,
endpointInterface = &amp;quot;org.apache.cxf.jms_greeter.JMSGreeterPortType&amp;quot;,
wsdlLocation = &amp;quot;file:./wsdl/jms_greeter.wsdl&amp;quot;)
public class GreeterJMSImpl implements JMSGreeterPortType {
//…
}
[/sourcecode]
  • portName = “GreeterPort” –> maps to wsdl:port attribute – name
  • serviceName = “JMSGreeterService” –> maps to wsdl:service attribute – name
  • targetNamespace = “http://cxf.apache.org/jms_greeter” –> wsdl:definitions attribute targetNamespace
  • endpointInterface = “org.apache.cxf.jms_greeter.JMSGreeterPortType” –> Interface that is implemente
  • wsdlLocation = “file:./wsdl/jms_greeter.wsdl” –> wsdl location on disc

Client

The Client class demonstrates how simple it is to call a JMS service using the wsdl URI –

[sourcecode lang=”java”] JMSGreeterService service = new JMSGreeterService(wsdl.toURI().toURL(), SERVICE_NAME);
JMSGreeterPortType greeter = (JMSGreeterPortType)service.getPort(PORT_NAME, JMSGreeterPortType.class);

System.out.println(&amp;quot;Invoking sayHi…&amp;quot;);
System.out.println(&amp;quot;server responded with: &amp;quot; + greeter.sayHi());
System.out.println();

System.out.println(&amp;quot;Invoking greetMe…&amp;quot;);
System.out.println(&amp;quot;server responded with: &amp;quot; + greeter.greetMe(System.getProperty(&amp;quot;user.name&amp;quot;)));
System.out.println();

System.out.println(&amp;quot;Invoking greetMeOneWay…&amp;quot;);
greeter.greetMeOneWay(System.getProperty(&amp;quot;user.name&amp;quot;));
System.out.println(&amp;quot;No response from server as method is OneWay&amp;quot;);
System.out.println();
[/sourcecode]

ActiveMQ

The demonstration stores the message queue in Memory –

[sourcecode lang=”java”] public final class EmbeddedBroker {
private EmbeddedBroker() { }

public static void main(String[] args) throws Exception {
BrokerService broker = new BrokerService();
broker.setPersistenceAdapter(new MemoryPersistenceAdapter());
broker.setDataDirectory(&amp;quot;target/activemq-data&amp;quot;);
broker.addConnector(&amp;quot;tcp://localhost:61616&amp;quot;);
broker.start();
System.out.println(&amp;quot;JMS broker ready …&amp;quot;);
Thread.sleep(125 * 60 * 1000);
System.out.println(&amp;quot;JMS broker exiting&amp;quot;);
broker.stop();
System.exit(0);
}
}
[/sourcecode]

Running The Example

mvn install (this will build the demo)

In separate command windows/shells:

mvn -Pjms.broker
mvn -Pserver
mvn -Pclient

With the output –

[sourcecode] INFO: Creating Service {http://cxf.apache.org/jms_greeter}JMSGreeterService from
WSDL: file:/…/apache-cxf-3.0.3/samples/jms_queue/src/main/config/jms_
greeter.wsdl
Invoking sayHi…
server responded with: Bonjour

Invoking greetMe…
server responded with: Hello Martin

Invoking greetMeOneWay…
No response from server as method is OneWay

Invoking sayHi with JMS Context information …
server responded with: Bonjour
Received expected contents in response context
[/sourcecode]

Apache CXF – Contract Last Example

This post looks at the JAX-WS “contract last”/”code first” implementation in samples\java_first_jaxws. This approach means that you create the Java code first, then create or generate the WSDL from that

Web Service Code

The web service uses JAX-WS annotations to annotate the interface and implementation. This generates the wsdl at runtime

Interface

[sourcecode lang=”java”] @WebService
public interface HelloWorld {

String sayHi(String text);

String sayHiToUser(User user);

@XmlJavaTypeAdapter(IntegerUserMapAdapter.class)
Map<Integer, User> getUsers();
}
[/sourcecode]

Implementation –

[sourcecode lang=”java”] @WebService(endpointInterface = "demo.hw.server.HelloWorld", serviceName = "HelloWorld")
public class HelloWorldImpl implements HelloWorld {
Map<Integer, User> users = new LinkedHashMap<Integer, User>();

public String sayHi(String text) {
System.out.println("sayHi called");
return "Hello " + text;
}

public String sayHiToUser(User user) {
System.out.println("sayHiToUser called");
users.put(users.size() + 1, user);
return "Hello " + user.getName();
}

public Map<Integer, User> getUsers() {
System.out.println("getUsers called");
return users;
}

}
[/sourcecode]

@WebService annotation denotes the class as a JAX-WS web service class. The parameters to this method are –

  • endpointInterface – Complete name of web service endpoint
  • name – Name of Web Service – maps to wsdl:portType
  • portName – Maps to wsdl:port
  • serviceName – Service endpont interface defined in Web Service contract
  • targetNamespace – Used for wsdl:portType and/or wsdl:service
  • wsdlLocation – Location of wsdl

The sayHi method takes a String, which is supported by JAX-WS, but we have to use XmlAdapter’s to support the User and Map objects in the other two methods

UserXmlAdapter

The User interface associates itself to the UserAdapter through the XmlJavaTypeAdapter annotation –

[sourcecode lang=”java”] @XmlJavaTypeAdapter(UserAdapter.class)
public interface User {
String getName();
}
[/sourcecode]

The User interface has its implementation under UserImpl, which links itself to the User type through the XmlType annotation –

[sourcecode lang=”java”] @XmlType(name = "User")
public class UserImpl implements User {
//…
}
[/sourcecode]

The mapping between the interface and implementation is then done through the XmlAdapter –

[sourcecode lang=”java”] public class UserAdapter extends XmlAdapter<UserImpl, User> {
public UserImpl marshal(User v) throws Exception {
if (v instanceof UserImpl) {
return (UserImpl)v;
}
return new UserImpl(v.getName());
}

public User unmarshal(UserImpl v) throws Exception {
return v;
}
}
[/sourcecode]

Map XmlAdapter

The getUsers method is interesting because it shows how XmlAdapter can be used as a workaround for JAXB not supporting Maps –

[sourcecode lang=”java”] public class IntegerUserMapAdapter extends XmlAdapter<IntegerUserMap, Map<Integer, User>> {
public IntegerUserMap marshal(Map<Integer, User> v) throws Exception {
IntegerUserMap map = new IntegerUserMap();
for (Map.Entry<Integer, User> e : v.entrySet()) {
IntegerUserMap.IntegerUserEntry iue = new IntegerUserMap.IntegerUserEntry();
iue.setUser(e.getValue());
iue.setId(e.getKey());
map.getEntries().add(iue);
}
return map;
}

public Map<Integer, User> unmarshal(IntegerUserMap v) throws Exception {
Map<Integer, User> map = new LinkedHashMap<Integer, User>();
for (IntegerUserMap.IntegerUserEntry e : v.getEntries()) {
map.put(e.getId(), e.getUser());
}
return map;
}
}
[/sourcecode]

CXFServlet and Spring Integration

The connectivity of the CXFServlet was covered in the previous post, and this section looks at how the cxf service is configured in cxf-servlet.xml –

[sourcecode lang=”xml”] <jaxws:server id="jaxwsService" serviceClass="demo.hw.server.HelloWorld" address="/hello_world">
<jaxws:serviceBean>
<bean class="demo.hw.server.HelloWorldImpl" />
</jaxws:serviceBean>
</jaxws:server>
[/sourcecode]

This connects in 3 key attributes –

  • serviceClass – HelloWorld interface
  • address – /hello_world – serving Url
  • serviceBean – HelloWorldImpl – implementation class

Running the example

The simplest way to run the example is through –

mvn clean install (builds the demo and creates a WAR file for optional Tomcat deployment)
mvn -Pserver (from one command line window — only if using a non-WAR standalone service)
mvn -Pclient (from a second command line window)

Or run in tomcat by dropping the war in the deploy directory, and accessing on –

http://localhost:8080/java_first_jaxws/services/hello_world?wsdl

This can be called from SOAPUI –

[sourcecode lang=”xml”] <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://server.hw.demo/">
<soapenv:Header/>
<soapenv:Body>
<ser:sayHiToUser>
<!–Optional:–>
<arg0>
<!–Optional:–>
<name>Martin</name>
</arg0>
</ser:sayHiToUser>
</soapenv:Body>
</soapenv:Envelope>
[/sourcecode]

You will get the output –

[sourcecode lang=”xml”] <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:sayHiToUserResponse xmlns:ns2="http://server.hw.demo/">
<return>Hello Martin</return>
</ns2:sayHiToUserResponse>
</soap:Body>
</soap:Envelope>
[/sourcecode]

Apache CXF – Contract/WSDL First

I introduced Apache CXF in my last post. I planned on writing some good examples of my own on using the framework, but to be honest I would struggle to beat the time and depth of examples the CXF download provides in its samples directory(Apache CXF Version 3)

Instead I decided it would be more interesting to provide commentary to some of these examples, including –

Thanks to the Apache CXF developers for providing this software, and these great examples. All code contained in this post is released by Apache under the Apache License.

WSDL First Demo

There are two approaches to building web services – contract first and contract last. Contract first is where the wsdl is defined first, and contract last is where the wsdl is defined last. Apache CXF supports both forms of development.

This example is found under apache-cxf\samples\wsdl_first, and is an examples of a contract first application

WSDL Contract

The wsdl follows the standard structure –

  • wsdl:types
  • wsdl:message
  • wsdl:operation
  • wsdl:binding
  • wsdl:service

It defines 2 operations –

  • <wsdl:operation name=”updateCustomer”>
  • <wsdl:operation name=”getCustomersByName”>

Finally the service defines 2 endpoints, one for standalone, and one for a tomcat deployment –

[sourcecode lang=”xml”] <wsdl:service name="CustomerServiceService">
<wsdl:port name="CustomerServicePort" binding="tns:CustomerServiceServiceSoapBinding">
<!– embedded deployment –>
<soap:address location="http://localhost:8080/wsdl_first/services/CustomerServicePort"/>
<!– Tomcat deployment, embedded or standalone –>
<!–soap:address location="http://localhost:8080/wsdl_first/services/CustomerServicePort"/–>
</wsdl:port>
</wsdl:service>
[/sourcecode]

Web Service Implementation – CustomerServiceImpl

The CustomerServiceImpl implements the CustomerService interface, which is created through the maven task – wsdl2java

[sourcecode lang=”java”] public class CustomerServiceImpl implements CustomerService {

// The WebServiceContext can be used to retrieve special attributes like the
// user principal. Normally it is not needed
@Resource
WebServiceContext wsContext;

public List&amp;lt;Customer&amp;gt; getCustomersByName(String name) throws NoSuchCustomerException {
// …
}

public void updateCustomer(Customer customer) {
// …
}

}
[/sourcecode]

The interface itself looks like, where you can see the autogenerated JAX-WS annotations –

[sourcecode lang=”java”] @WebService(targetNamespace = &amp;quot;http://customerservice.example.com/&amp;quot;, name = &amp;quot;CustomerService&amp;quot;)
@XmlSeeAlso({ObjectFactory.class})
public interface CustomerService {

@Oneway
@RequestWrapper(localName = &amp;quot;updateCustomer&amp;quot;,
targetNamespace = &amp;quot;http://customerservice.example.com/&amp;quot;,
className = &amp;quot;com.example.customerservice.UpdateCustomer&amp;quot;)
@WebMethod
public void updateCustomer(@WebParam(name = &amp;quot;customer&amp;quot;, targetNamespace = &amp;quot;&amp;quot;)
com.example.customerservice.Customer customer
);

@WebResult(name = &amp;quot;return&amp;quot;, targetNamespace = &amp;quot;&amp;quot;)
@RequestWrapper(localName = &amp;quot;getCustomersByName&amp;quot;,
targetNamespace = &amp;quot;http://customerservice.example.com/&amp;quot;,
className = &amp;quot;com.example.customerservice.GetCustomersByName&amp;quot;)
@WebMethod
@ResponseWrapper(localName = &amp;quot;getCustomersByNameResponse&amp;quot;,
targetNamespace = &amp;quot;http://customerservice.example.com/&amp;quot;,
className = &amp;quot;com.example.customerservice.GetCustomersByNameResponse&amp;quot;)
public java.util.List&amp;lt;com.example.customerservice.Customer&amp;gt; getCustomersByName(
@WebParam(name = &amp;quot;name&amp;quot;, targetNamespace = &amp;quot;&amp;quot;) java.lang.String name
) throws NoSuchCustomerException;

}
[/sourcecode]

CXFServlet

web.xml defines the CXFServlet –

[sourcecode lang=”xml”] <servlet>
<description>Apache CXF Endpoint</description>
<display-name>cxf</display-name>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
[/sourcecode]

The CXFServlet adds a Spring context, which is defined through a file called cxf.xml. This defines the end point, this is the default name and could be changed through web.xml configuration –

[sourcecode lang=”xml”] <!– comment this bean to disable schema validation in the client –>
<jaxws:client name="{http://apache.org/hello_world_soap_http}SoapPort" createdFromAPI="true">
<jaxws:properties>
<entry key="schema-validation-enabled" value="true"/>
</jaxws:properties>
</jaxws:client>
<jaxws:endpoint name="{http://apache.org/hello_world_soap_http}SoapPort"
wsdlLocation="wsdl/CustomerService.wsdl" createdFromAPI="true">
<jaxws:properties>
<entry key="schema-validation-enabled" value="true"/>
</jaxws:properties>
</jaxws:endpoint>
[/sourcecode]

Server Implementation

The intention of this tutorial is to deploy to JBoss Fuse, but I thought it was interesting to look at the different options offered in this example. The first uses JAX-WS or Spring

Spring – Injection of endpoint into jaxws server –

[sourcecode lang=”xml”] <!– HTTP Endpoint –>
<jaxws:endpoint xmlns:customer="http://customerservice.example.com/" id="CustomerServiceHTTP" address="http://localhost:8080/wsdl_first/services/CustomerServicePort" serviceName="customer:CustomerServiceService" endpointName="customer:CustomerServiceEndpoint" implementor="com.example.customerservice.server.CustomerServiceImpl">
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature"/>
</jaxws:features>
</jaxws:endpoint>
[/sourcecode]

JAX-WS – The Endpoint is coded directly –

[sourcecode lang=”java”] CustomerService implementor = new CustomerServiceImpl();
EndpointImpl ep = (EndpointImpl)
Endpoint.publish(&amp;quot;http://localhost:8080/wsdl_first/services/CustomerServicePort&amp;quot;, implementor);

// Adding logging for incoming and outgoing messages
ep.getServer().getEndpoint().getInInterceptors().add(new LoggingInInterceptor());
ep.getServer().getEndpoint().getOutInterceptors().add(new LoggingOutInterceptor());
[/sourcecode]

Build (pom.xml)

The core part of the pom is the cxf-codegen-plugin. This plugin takes the wsdl and generates the java source code through its wsdl2java goal –

[sourcecode lang=”xml”] <plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<wsdlOptions>
<wsdlOption>
<wsdl>src/main/resources/CustomerService.wsdl</wsdl>
<frontEnd>jaxws21</frontEnd>
<faultSerialVersionUID>1</faultSerialVersionUID>
<bindingFiles>
<bindingFile>src/main/resources/binding.xml</bindingFile>
</bindingFiles>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
[/sourcecode]

Key points –

  • <id> and <phase> – generate-sources
  • <wsdl> – allows multiple wsdls
  • <binding> – This is a specific binding for Java to use Java consistent date formats instead of the default XMLGregorianCalendar

Putting it all together

The tutorial instructions are quite simple –

mvn clean install   (builds the demo and creates a WAR file for optional Tomcat deployment)
mvn -Pserver  (from one command line window — only if using embedded Jetty)
mvn -Pclient  (from a second command line window)

Or change the CustomerService.wsdl, and rerun maven. Then copy the wsdl_first.war to the deploy directory of tomcat. You can test the installation by running –

http://localhost:8080/wsdl_first/services/CustomerServicePort?wsdl

You can then test this installation using a tool like SOAPUI, and sending a message like –

[sourcecode lang=”xml”] <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cus="http://customerservice.example.com/">
<soapenv:Header/>
<soapenv:Body>
<cus:getCustomersByName>
<!–Optional:–>
<name>Martin</name>
</cus:getCustomersByName>
</soapenv:Body>
</soapenv:Envelope>
[/sourcecode]

Or to update the customer –

[sourcecode lang=”xml”] <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cus="http://customerservice.example.com/">
<soapenv:Header/>
<soapenv:Body>
<cus:updateCustomer>
<!–Optional:–>
<customer>
<customerId>0</customerId>
<!–Optional:–>
<name>Smith</name>
</customer>
</cus:updateCustomer>
</soapenv:Body>
</soapenv:Envelope>
[/sourcecode]

The tomcat log shows the interaction

update request was received
Customer was updated

parkrunPB – Hibernate ORM

There are a number of different approaches to connect a Java application to a database. These include –

  • JDBC
  • JPA
  • Spring SQL Templates
  • Object Relational Mappers – Toplink, Hibernate

I have opted for Hibernate for this application as its one of the most common ORM’s.

The advantages of an ORM are –

  • Reduce development time and costs
  • Vendor independence

The disadvantages are –

  • SQL can be poor quality
  • Poor preformance on complex queries
  • Developers can have poor understanding of SQL

Spring/Hibernate Configuration – spring-servlet.xml

 	<bean id="propertyConfigurer"
 		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
 		p:location="/WEB-INF/jdbc.properties" /> 
 	<bean id="dataSource"
 	      class="org.apache.commons.dbcp.BasicDataSource"
 		  destroy-method="close"
 		  p:driverClassName="com.mysql.jdbc.Driver"
 		  p:url="jdbc:mysql://127.0.0.1:3306/test"
 		  p:username=""
 		  p:password="" /> 
 	<bean id="sessionFactory"
 		  class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
 		<property name="dataSource" ref="dataSource" />
         <property name="annotatedClasses">
            <list>
               <value>com.glenware.parkrunpb.form.PRCourse</value>
               <value>com.glenware.parkrunpb.form.PRRegion</value>
            </list>
         </property>
 	 <property name="configurationClass">
 		<value>org.hibernate.cfg.AnnotationConfiguration</value>
	 </property>
 	 <property name="hibernateProperties">
 		<props>
 			<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
 			<prop key="hibernate.show_sql">true</prop>
			<prop key="hibernate.lazy">false</prop>
		</props>
 	</property>
 	</bean> 
 	<bean id="transactionManager"
 		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
 		<property name="sessionFactory" ref="sessionFactory" />
 	</bean>

Key points –

  • dataSource – this is configured with the url/username/password for the mysql instance being used. Another option is the jdbc.properties file
  • sessionFactory – The configuration states we are only looking at annotations in –
    • AnnotationSessionFactoryBean
    • PRCourse and PRRegion
    • MySQLDialect – this is the SQL dialect getting used in Hibernate – other options include
  • transactionManager – We also need a TransactionManager, in this case HibernateTransactionManager

Table Mapping

One of the advantages is the ease with which tables can be mapped from the SQL DDL to the Java Object. Consider –

CREATE TABLE `prcourse` (
`prcourse_id` int(11) NOT NULL AUTO_INCREMENT,
`prregion_id` int(11),
`prname` varchar(256) DEFAULT NULL,
`url` varchar(256) DEFAULT NULL,
`averagetime` int(11) DEFAULT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`prcourse_id`)
INDEX par_ind (`prregion_id`),
FOREIGN KEY (`prregion_id`)
)

Here the mapping is fairly simple –

  • @Table(name = “PRCOURSE”) – maps to table
  • @Id maps the primary key
  • @Column maps the column names
@Entity
@Table(name = "PRCOURSE")
public class PRCourse {
@Id
@Column(name = "PRCOURSE_ID")
@GeneratedValue
private Integer id;
@Column(name = "PRNAME")
@NotEmpty
private String prName;
@Column(name = "URL")
@NotEmpty
private String url;
@Column(name = "AVERAGETIME")
@Range(min = 1)
private int averageTime;
@ManyToOne
@JoinColumn(name="PRREGION_ID")
private PRRegion prregion;
}

The most complex part of this configuration is the one to many relationship between PRCourse and PRRegion, where we use the @ManyToOne annotation. The corresponding mapping ties prregion to PRCourse –

@OneToMany(mappedBy="prregion")
 private Set prCourses;

 

Accessing Data

This would be best explained using a UML diagram to show ParkrunDAOImpl implementing ParkrunDAO, and I’ll try and get round to adding one.

@Repository
@Transactional
public class ParkrunDAOImpl implements ParkrunDAO {
   @Autowired
   private SessionFactory sessionFactory;
   @Override
   public void addPRCourse(PRCourse prCourse) {
      sessionFactory.getCurrentSession().save(prCourse);
   }
   @Override
   public PRCourse getPRCourse(Integer id) {
      return (PRCourse) sessionFactory.getCurrentSession().get(PRCourse.class, id);
   }
   @Override
   public List<PRCourse> listPRCourse() {
      return sessionFactory.getCurrentSession().createQuery("from PRCourse order by prName").list();
   }
   @Override
   public void removePRCourse(Integer id) {
      PRCourse prCourse = (PRCourse) sessionFactory.getCurrentSession().load(PRCourse.class, id);
      if (prCourse != null) {
         sessionFactory.getCurrentSession().delete(prCourse);
      }
   }
   @Override
   public PRRegion getPRRegion(Integer id) {
      return (PRRegion) sessionFactory.getCurrentSession().get(PRRegion.class, id);
   }
   @Override
   public List<PRRegion> listPRRegion() {
      return sessionFactory.getCurrentSession().createQuery("from PRRegion order by regionName").list();
   }
}

The key point are –

  • SessionFactory – this creates the connection to the database
  • get method – return a specific instance
  • createQuery – HQL – Hibernate specific query
  • save – Add to database
  • delete – Delete from database

SQL Inserts

This section contains the SQL should you wish to populate your database instance –

 

CREATE TABLE `prcourse` (
`prcourse_id` int(11) NOT NULL AUTO_INCREMENT,
`prregion_id` int(11),
`prname` varchar(256) DEFAULT NULL,
`url` varchar(256) DEFAULT NULL,
`averagetime` int(11) DEFAULT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`prcourse_id`)
INDEX par_ind (`prregion_id`),
FOREIGN KEY (`prregion_id`)
)
CREATE TABLE `prregion` (
 `prregion_id` int(11) NOT NULL AUTO_INCREMENT,
 `regionname` varchar(256) DEFAULT NULL,
 `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
 PRIMARY KEY (`prregion_id`)
)

Inserts

 INSERT INTO PRREGION(REGIONNAME) VALUES ('East Midlands');
 INSERT INTO PRREGION(REGIONNAME) VALUES ('East of England');
 INSERT INTO PRREGION(REGIONNAME) VALUES ('Greater London');
 INSERT INTO PRREGION(REGIONNAME) VALUES ('North East England');
 INSERT INTO PRREGION(REGIONNAME) VALUES ('North West England');
 INSERT INTO PRREGION(REGIONNAME) VALUES ('Northern Ireland');
 INSERT INTO PRREGION(REGIONNAME) VALUES ('Overseas Military Bases');
 INSERT INTO PRREGION(REGIONNAME) VALUES ('Scotland');
 INSERT INTO PRREGION(REGIONNAME) VALUES ('South East England');
 INSERT INTO PRREGION(REGIONNAME) VALUES ('South West England');
 INSERT INTO PRREGION(REGIONNAME) VALUES ('Wales');
 INSERT INTO PRREGION(REGIONNAME) VALUES ('West Midlands');
 INSERT INTO PRREGION(REGIONNAME) VALUES ('Yorkshire and Humberside');
  INSERT INTO prcourse(prregion_id, prname, url, averagetime) VALUES (11, 'Inverness', 'http://www.parkrun.org.uk/inverness/', 1582);
 INSERT INTO prcourse(prregion_id, prname, url, averagetime) VALUES (11, 'Aberdeen', 'http://www.parkrun.org.uk/aberdeen/', 1586);
 INSERT INTO prcourse(prregion_id, prname, url, averagetime) VALUES (11, 'Dundee(Camperdown)', 'http://www.parkrun.org.uk/camperdown/', 1752);
 INSERT INTO prcourse(prregion_id, prname, url, averagetime) VALUES (11, 'St Andrews', 'http://www.parkrun.org.uk/standrews/', 1669);
 INSERT INTO prcourse(prregion_id, prname, url, averagetime) VALUES (11, 'Perth', 'http://www.parkrun.org.uk/perth/', 1620);
 INSERT INTO prcourse(prregion_id, prname, url, averagetime) VALUES (11, 'Edinburgh', 'http://www.parkrun.org.uk/edinburgh/', 1523);
 INSERT INTO prcourse(prregion_id, prname, url, averagetime) VALUES (11, 'Falkirk', 'http://www.parkrun.org.uk/falkirk/', 1612);
 INSERT INTO prcourse(prregion_id, prname, url, averagetime) VALUES (11, 'Tollcross', 'http://www.parkrun.org.uk/tollcross/', 1623);
 INSERT INTO prcourse(prregion_id, prname, url, averagetime) VALUES (11, 'Strathclyde', 'http://www.parkrun.org.uk/strathclyde/', 1586);
 INSERT INTO prcourse(prregion_id, prname, url, averagetime) VALUES (11, 'Victoria', 'http://www.parkrun.org.uk/victoria/', 1526);
 INSERT INTO prcourse(prregion_id, prname, url, averagetime) VALUES (11, 'Glasgow', 'http://www.parkrun.org.uk/glasgow/', 1585);
 INSERT INTO prcourse(prregion_id, prname, url, averagetime) VALUES (11, 'Eglington', 'http://www.parkrun.org.uk/eglinton/', 1681);

parkrunPB – Spring MVC/Hibernate Application

I wrote this app to demonstrate some of the features of a number of technologies, and primarily Spring MVC.

The main technologies I’ll be demonstrating are –

  • Twitter Bootstrap and WebJar
  • Spring 3 and Spring MVC
  • Hibernate
  • Mockito
  • Jackson JSON RESTFUL API

The source code can be downloaded from https://github.com/farrelmr/parkrunPB

Ive deliberately not strayed into proper Spring 4 MVC/Java 8 territory as I want to cover these in a future tutorial

parkrunPB

The application itself is based on one of my favourite hobbies parkrunning. These are free weekly 5km running time trials, which started in London, but have expanded throughout the UK and globally. They are open to all, so you see everything from Olympic athletes to walkers. You also have people running with buggies or dogs. If your into running or want to get into running then it’s a good place to start.

The application is fairly simple – take your 5k time at one parkrun, then estimate your time on other courses by using the ratio of average times for the courses. Ive restricted the courses to only those in Scotland – but you could add more.

Spring 4 Simple Example

The tutorial provides a simple Spring 4 application. The application demonstrates how Spring can be used to “inject” the Bicycle choice to our Cyclist object through dependency injection.

The code can be downloaded from – www.github.com/farrelmr/spring4DI

An installation guide for this code is available at Spring 4 Simple Example Installation

The project layout is –

Spring4 DI Directory Structure

To run the code run the RunMe application

You can rebuild this code for Spring 3 by amending the pom.xml file –

[sourcecode lang=”xml”] <spring.version>4.0.6.RELEASE</spring.version>
[/sourcecode]

Model

The Model objects in our Spring 4 universe are –

  • Cyclist
  • RacingBike implements Bicycle
  • MountainBike implements Bicycle

Without Dependency Injection(DI)

If we were to implement this code without DI it might look like this –

[sourcecode lang=”java”] package com.glenware.spring4;

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

public class RunMe {
public static void main(String[] args) {
Cyclist roadCyclist = new Cyclist();
roadCyclist.setBicycle(new RoadBicycle());
roadCyclist.setCyclingSong("I want to ride my bicycle, I want to ride my bike");
System.out.println(roadCyclist.getCyclingSong());
roadCyclist.getBicycle().wotYouRiding();
}
}
[/sourcecode]

Giving an output –

I want to ride my bicycle, I want to ride my bike
Im riding my road bike

With Dependency Injection(DI)

On a small scale this code is fine – but as the code base grows having the setters repeatedly add bloat to the code, something which DI removes.

The model does not have to change for this example, instead we configure the Cyclist and Bicycle’s through the Spring 4 xml configuration –

[sourcecode lang=”xml”] <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-4.0.xsd">

<bean id="roadBike" class="com.glenware.spring4.RoadBicycle" />
<bean id="roadCyclist" class="com.glenware.spring4.Cyclist">
<property name="cyclingSong" value="I want to ride my bicycle, I want to ride my bike" />
<property name="bicycle" ref="roadBike" />
</bean>

<bean id="mountainBike" class="com.glenware.spring4.MountainBicycle" />
<bean id="offroadCyclist" class="com.glenware.spring4.Cyclist">
<property name="cyclingSong" value="I run around town, around round the round with the pedal to the met…. The pedal to whatever" />
<property name="bicycle" ref="mountainBike" />
</bean>

</beans>
[/sourcecode]

The key construct here is the allocation of properties, where instead of using the setters in the code, we use the property fields. Note there are two types of property – value which refers to a value object(eg. String), or ref which refers to a complex object.

The code to execute –

[sourcecode lang=”java”] package com.glenware.spring4;

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

public class RunMe {
public static void main(String[] args) {
@SuppressWarnings("resource")
ApplicationContext context = new ClassPathXmlApplicationContext("springCyclingBeans.xml");

Cyclist roadCyclist = (Cyclist) context.getBean("roadCyclist");
System.out.println(roadCyclist.getCyclingSong());
roadCyclist.getBicycle().wotYouRiding();

Cyclist offroadCyclist = (Cyclist) context.getBean("offroadCyclist");
System.out.println(offroadCyclist.getCyclingSong());
offroadCyclist.getBicycle().wotYouRiding();
}
}
[/sourcecode]

Output

I want to ride my bicycle, I want to ride my bike
Im riding my road bike
I run around town, around round the round with the pedal to the met…. The pedal to whatever
Im riding my mountain bike

The new code calls the ApplicationContext. This loads handles our object creation, and lifecycle.

To call the specific implementation we simply request the name we gave the bean in the spring configuration file –

[sourcecode lang=”java”] Cyclist offroadCyclist = (Cyclist) context.getBean("offroadCyclist");
[/sourcecode]