Tuesday, 21 August 2012

Classpath error snippet

File Not Found (Classpath Resource)

If this is encountered, either try modifying the classpath or prepending the file location with 'file://'

Spring Jersey Contrib

Adding Jersey to a spring webapp

Since jersey has its own servlet that would normally take the REST requests, it's difficult to wire this in with Spring beans. That's where the spring contrib library comes in. Instead of having the WEB-INF/web.xml use the servlet com.sun.jersey.spi.container.servlet.ServletContainer, you can use the below com.sun.jersey.spi.spring.container.servlet.SpringServlet.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="WebApp_ID" version="2.5">

 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:application-context.xml</param-value>
 </context-param>

 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

 <servlet>
  <servlet-name>service</servlet-name>
  <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
  <init-param>
   <param-name>com.sun.jersey.config.feature.DisableWADL</param-name>
   <param-value>true</param-value>
  </init-param>
  <init-param>
   <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
   <param-value>true</param-value>
  </init-param>
 </servlet>
 <servlet-mapping>
  <servlet-name>service</servlet-name>
  <url-pattern>/*</url-pattern>
 </servlet-mapping>
</web-app>

Maven dependency

Adding this using maven would consist of the following.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!-- Jersey + Spring -->
<dependency>
 <groupId>com.sun.jersey.contribs</groupId>
 <artifactId>jersey-spring</artifactId>
 <version>${jersey.version}</version>
 <exclusions>
  <exclusion>
   <groupId>org.springframework</groupId>
   <artifactId>spring</artifactId>
  </exclusion>
  <exclusion>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
  </exclusion>
  <exclusion>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
  </exclusion>
  <exclusion>
   <groupId>org.springframework</groupId>
   <artifactId>spring-beans</artifactId>
  </exclusion>
  <exclusion>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
  </exclusion>
 </exclusions>
</dependency>

Friday, 17 August 2012

Spring web

Servlets and Naming

When defining a spring web project, requests come through to the DispatcherServlet. Therefor this must be defined in the WEB-INF/web.xml.

1
2
3
4
5
6
7
8
9
<servlet>
    <servlet-name>test</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
    
<servlet-mapping>
    <servlet-name>test</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

The important thing to note with this config is the name however. The name test is used and will result in spring looking for a WEB-INF/test-servlet.xml.

Components and Config

Now that the servlet is defined, the config that goes into spring can be configured. With this example i'm using component scan to pickup beans automatically and i'm specifying the view finder which i'll explain next.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

 <context:component-scan base-package="com.aphexmunky.web" />

 <mvc:annotation-driven />

 <mvc:resources location="/resources/" mapping="/resources/**" />

 <bean
  class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
  <property name="prefix" value="/WEB-INF/views/" />
  <property name="suffix" value=".jsp" />
 </bean>

</beans>

So the InternalResourceViewResolver points to locations where spring can find files. Should a bean return a String "home", it will then as part of it's view cycle go to /WEB-INF/views/home.jsp to find the content. The jsp could be anything really but here is an example of the bean.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package com.aphexmunky.web;

import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeController {
 
 @RequestMapping({"/","/home"})
 public String showHomePage(Map<String, Object> model) {
  model.put("hello", "Hello, World!");
  return "home";
 }
}

Thursday, 16 August 2012

Spring config

Properties

Using properties files is a handy way of externalizing the config without forcing people to play about with spring xml. The easiest way of dealing with this is though PropertyPlaceholderConfigurer. You can pass to it a property set of locations which then is a list of locations. See the snippet below.

1
2
3
4
5
6
7
8
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
 <property name="locations">
  <list>
   <value>classpath:warehouse.adaptor.properties</value>
   <value>classpath:warehouse.adaptor.scheduler.properties</value>
  </list>
 </property>
</bean>

These properties can then be referenced through ${}.

Wednesday, 15 August 2012

Spring

Spring Wiring

To begin wiring spring beans together we need to create an applicationContext.xml. That looks like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?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.xsd"
 default-autowire="byType">

 <bean id="knight" class="com.aphexmunky.spring.BraveKnight"/>
 
 <bean id="quest" class="com.aphexmunky.spring.Quester" />

</beans>

With these two beans explicitly wired, we can create spring and grab our beans out of it.

1
2
ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
Knight knight = ac.getBean(Knight.class);

Autowiring

Autowiring can be done by annotating a private member with @Autowired. For this to work however the bean still needs to be defined.

However, there is spring context which can allow us to find beans automatically. The following needs to be added to the spring config file.

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

 <context:component-scan base-package="com.aphexmunky.spring" />

</beans>

With this configuration, we've added spring context to the xml namespace and added context:component-scan which allows spring to find beans annotated with certain annotations and automatically consider them beans. They are

  • @Component
  • @Controller
  • @Repository
  • @Service

With these, any bean annotated with one and in the base-package specified can now be instantiated by spring.


spring xsd locations

Sunday, 12 August 2012

Refs

Updating refs

Refs, unlike atoms are a coordinated. They are however like Atoms, synchronous. All updates to refs must be done within a transaction. This can be done by wrapping the changes within a dosync block.

Alter

alter is the most like swap!. It will always be applied in the order designed and it makes no assumptions the re-orderability.

Commute

Commute is used when the order the changes are applied does not matter. It gets its name from commutative. Commute never attempts to retry and as such can be significantly faster.

Ref-set

Ref-set, like alter will retry on values. It is generally only used to to reinitialise refs state to starting values.

Validators

Validators must return true for a transactional change to take place. They can be applied using :validator fn.

The dark side of STM

The problem with all these retries that the STM provides is that it has no idea if what you're doing is unsafe. If you're writing to database, you don't want it written multiple times while another part of your application fails and the whole thing retries. For that reason there is an io! macro which throws an error if done within a transaction.

Saturday, 11 August 2012

Atoms

Practicality

Atoms are uncoordinated and synchronous reference types. Their name comes from the atomic nature. The most common way of manipulating them is through swap!.

(def sarah (atom {:name "Sarah" :age 25 :wears-glasses? false}))

(swap! sarah update-in [:age] + 3)

(swap! sarah (comp #(update-in % [:age] inc) #(assoc % :wears-glasses? true)))

Should an atom change during the swap! operation, it will automatically retry the operation. It will keep retrying until it updates undisturbed.

Reset!

reset is a way of changing an atoms value with no regard to what its current value is.

(reset! sarah :y)
:y


delays, futures and promise

Delay

Delay is a concurrency function that delays the execution of some code until it is wanted.

(def s (delay (slurp "http://squidoop.blogspot.co.uk/")))
s
#<Delay@26e7127: :pending>
@s
"<!DOCTYPE html>\n<ht...

The code takes some time to execute on the first run, however once it is realized it is cached and the next dereference will be typical execution of any string.

Future

Future is an idiomatic way of creating execution for a new thread. Unlike native Java that requires a implmentation of Runnable for a piece of code, any function wrapped in a future will create and start a new thread but return execution immediately. You can use the ref of the future straight away however it may not be fully realized when you use it.

Unlike delays however, you can specify a timeout when dereferencing a future.

(deref (future (Thread/sleep 5000) :done!) 1000 :impatient!)
:impatient!

Promise

A promise is a completely uninitialised value. You promise to deliver a value to it some point in time later.

user=> (def p (promise))
#'user/p
user=> p
#<core$promise$reify__6153@5200089: :pending>
user=> (realized? p)
false
user=> (deliver p 42)
#<core$promise$reify__6153@5200089: 42>

Combining a future promise

(def a (promise))
(def b (promise))
(def c (promise))
(future (deliver c (+ @a @b)) (println "Delivery complete!"))

The future can't deliver because both a and b are unrealised promises.

(deliver a 15)
;= #<core$promise$reify__5727@56278e83: 15>
(deliver b 16)
; Delivery complete!
;= #<core$promise$reify__5727@47ef7de4: 16>
@c
;= 31

As soon as both promises have been delivered, the future stops being blocked and the delivery execution happens.