NoSQL in Enterprise Java Applications - GOTO Blog...
Transcript of NoSQL in Enterprise Java Applications - GOTO Blog...
![Page 1: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/1.jpg)
NoSQL in Enterprise Java Applications
Patrick Baumgartner
NoSQL Search Roadshow | Munich | 16.04.2013
![Page 2: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/2.jpg)
2
Agenda
• Speaker Profile • New Demands on Data Access • New Types of Data Stores • Polyglot Persistence • Integrating NoSQL Data Stores • Spring Data Overview • Example with MongoDB • Example with Neo4j • Highlights and Challenges • Q & A
![Page 3: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/3.jpg)
3
Speaker Profile
Patrick Baumgartner
• Senior Software Consultant | Partner @ Swiftmind
• Spring Framework, OSGi, Neo4j • Spring Trainer • Co-Autor von „OSGi für Praktiker“
• Agile Methodologies & Practices • Scrum.org Trainer - PSD Java
• @patbaumgartner
![Page 4: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/4.jpg)
4
Swiftmind
Your experts for Enterprise Java Areas of expertise • Java EE • Spring Framework • OSGi • Agile Methodologies • Software Engineering Best Practices
Headquarter • Zürich, Schweiz • @swiftmind • http://www.swiftmind.com
![Page 5: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/5.jpg)
5
New Demands on Data Access
• Structured and unstructured data
• Massive amounts of data • Inexpensive horizontal
scaling • Apps and data in the
cloud • Social network features • …
![Page 6: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/6.jpg)
6
New Types of Data Stores
![Page 7: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/7.jpg)
7
NoSQL
Data Size
Data Complexity
Key-Value Stores
Column Family
Document Databases
Graph Databases
Relational Databases
90%
![Page 8: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/8.jpg)
8
One single data store for your application? Polyglot Persistence
![Page 9: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/9.jpg)
9
Polyglot Persistence Web Shop
User Sessions Shopping Card Recommendations
Product Catalog Analytics Financial Data
Redis Riak Neo4j
MongoDB Casandra MySQL
![Page 10: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/10.jpg)
10
We are not architects! Integrating NoSQL Data Stores #1
http://www.flickr.com/photos/sakeeb/4087246274
![Page 11: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/11.jpg)
11
Don’t re-invent the wheel! Integrating NoSQL Data Stores #2
http://www.flickr.com/photos/dmott9/5921728819
![Page 12: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/12.jpg)
12
Let’s use Spring! Integrating NoSQL Data Stores #3
http://www.springsource.org/spring-data
![Page 13: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/13.jpg)
13
Spring Data
• Same goals as the Spring Framework – Productivity improvement – Programming model consistency – Portability
• Umbrella for subprojects, specific to a given database • Mapping support for Java domain objects
• http://www.springsource.org/spring-data • http://github.com/SpringSource/spring-data-XXX
![Page 14: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/14.jpg)
14
Spring Data – Overview #1
• JPA • JDBC Extensions
Relational Databases
• Apache Hadoop Big Data
• GemFire Data Grid
• REST HTTP
• Redis
Key Value Stores
![Page 15: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/15.jpg)
15
Spring Data – Overview #2
• Mongo DB • Couchbase *
Document Stores
• Neo4J Graph Databases
• Hbase Column Stores
• Apache Solr * • Elastic Search *
Search
• Commons Common Infrastructure
* Community Project
![Page 16: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/16.jpg)
16
Spring Data – Key Features
• Low level data access API abstraction – MongoTemplate, RiakTemplate, Neo4jTemplate … – Exception translation – Transaction management
• Object Mapping (Java to data store) • Generic Repository Support
– Basic CRUD, dynamic finders, pagination and sorting • Spring namespaces • Cross Store Persistence Programming Model
– @Entity, @Document, @NodeEntity …
![Page 17: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/17.jpg)
17
Spring Data MongoDB – Example
![Page 18: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/18.jpg)
18
Documents
Stored JSON: { "_id" : ObjectId("4f9886290364b533b3acd4ce"), "_class" : "com.acme.hello.domain.Person", "name" : "Bob", "age" : 33 }
![Page 19: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/19.jpg)
19
Spring Data MongoDB – Document
Stored JSON: { "_id" : ObjectId("4f9886290364b533b3acd4ce"), "_class" : "com.example.Person", "name" : "Bob", "age" : 33 }
@Document public class Person { @Id private int id;
private String name;
private int age;
// getters/setters… }
![Page 20: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/20.jpg)
20
Spring Data MongoDB – Configuration
![Page 21: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/21.jpg)
21
Spring Data MongoDB – Repository
@Repository public class MongoPersonRepository implements BaseRepository<Person> {
@Autowired MongoOperations mongoTemplate;
Person createPerson(String name, int age){
if(!mongoTemplate.collectionExists(Person.class)){
mongoTemplate.createCollection(Person.class);
}
Person p = new Person(name, age);
mongoTemplate.insert(p)
return p;
}
...
}
![Page 22: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/22.jpg)
22
Spring Data MongoDB – Repository #2
@Repository public interface MongoPersonRepository implements CrudRepository<Person, Long> {
Page<Person> findByNameContaining(String name, Pageable p);
@Query("{ ?0 : ?1 }") List<Product> findByAttributes(String key, String value);
}
![Page 23: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/23.jpg)
23
Spring Data Neo4j – Example
![Page 24: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/24.jpg)
24
Graph
![Page 25: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/25.jpg)
25
Social Data
Alice Carol Luke
Bob
Sam
Pete KNOWS
KN
OW
S
KNOWS KNOWS
![Page 26: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/26.jpg)
26
The only use case? Social Graph
![Page 27: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/27.jpg)
27
Spatial Data
1 2 5
3
13
8 ROAD
RO
AD
ROAD type:ROAD length:3km
type:Hotel name:Radisson Blu lat:47.452549 long:8.564615
type:Hotel name:Widder lat:47.373517 long:8.539252
![Page 28: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/28.jpg)
28
Social & Spatial Data
Alice Mat 5
Bob
13
8 ROAD
RO
AD
LIKES KNOWS
type:Hotel name:Radisson Blu lat:47.452549 long:8.564615
![Page 29: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/29.jpg)
29
Financial Data
Alice Hotel Luke
Bank
ATM
Pete WITHDRAW
TRANSFER OWNS
![Page 30: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/30.jpg)
30
Your business domain
Process
KPI
Device
Activity
Function
Service DEPENDS_ON D
EPEN
DS_
ON
![Page 31: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/31.jpg)
31
Spring Data Neo4j (SDN)
• POJOs mapped as nodes or relationships – type safe • Works directly Database, typically embedded mode • Data is fetched very fast and lazy • Stores everything within a @Transaction • Uses heavily AspectJ magic to enhance the POJOs • …
![Page 32: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/32.jpg)
32
Spring Data Neo4j – NodeEntity
_type_: com.example.Person name: "Alice" age: 42
@NodeEntity public class Person { private String name;
private int age;
// getters/setters…
}
Person alice = new Person();
alice.setName("Alice");
alice.setAge(42);
alice.persist();
Node
![Page 33: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/33.jpg)
33
Spring Data Neo4j – Relationship
@RelationshipEntity public class Knows { private int sinceYear; public Knows since(int year) { this.sinceYear = year; return this; } } @NodeEntity public class Person { public Known knows(Person p) { return this.relateTo(p, Knows.class, "KNOWS"); } } Person alice = ...; Person bob ...; alice.knows(bob).since(2012);
Alice Bob KNOWS since: 2012
![Page 34: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/34.jpg)
34
Spring Data Neo4j – NodeEntity
@NodeEntity public class Person { private String name; private int yearOfBirth; @RelatedTo(type = "KNOWS", direction = Direction.OUTGOING) private Set<Person> knownPersons; public void knows(Person p) { knownPersons.add(p); } public Set<Person> getFriends() { return knownPersons; } } Person alice = ...; alice.knows(bob); alice.knows(carol);
Alice Bob KNOWS
Carol
KNOWS
![Page 35: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/35.jpg)
35
Spring Data Neo4j – Repository
public interface PersonRepository extends GraphRepository<Person> {
@Query("start person = {0} match ... return ...")
Iterable<Product> getOwnedServices(Person person);
Iterable<Person> findByName(String name);
Iterable<Person> findByNameLike(String name);
}
@Autowired
PersonRepository personRepository;
Person alice = personRepository.findByName("Alice");
![Page 36: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/36.jpg)
36
Spring Data Neo4j – Querying
• Several possibilities implemented to query the graph – Neo4j API – Traversal descriptions – Graph algorithms – Index queries – Cypher queries
![Page 37: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/37.jpg)
37
Highlights and Challenges
![Page 38: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/38.jpg)
38
Highlights
• Vibrating community, great support on mailing lists
• Using the right tool for the right job • New technologies differentiate our product/service from
competitors
• Sources on github.com – Pull requests for improvements • Very good overall performance
• We can use Spring!
• Abstraction layer makes “driver” changes easy
![Page 39: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/39.jpg)
39
Challenges
• Developer Onboarding
• Schema changes -> migrations
• Some topics not solved yet -> e.g. versioning
• Not many show cases documented in detail
• Sizing for scaling based on real world measurements • Massive amount of data
• Several framework and data store releases per year
• Bugs, but no show stoppers
• Keeping documentation up-to-date, data model changes
![Page 40: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/40.jpg)
40
Information from the source Spring Data
Hive Pig JDBC HBase JPA
Splunk NoSQL Redis BigData
Hadoop Redis Roo Gemfire
MongoDB Neo4j REST exporter
Querydsl Repositories
http://bit.ly/sd-book
![Page 41: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/41.jpg)
41
Use a data model which really matches to your data … Give it a try!
http://www.flickr.com/photos/juniorvelo/3267647833
![Page 42: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/42.jpg)
42
Q&A
![Page 43: NoSQL in Enterprise Java Applications - GOTO Blog ...nosqlroadshow.com/dl/NoSQL-Munich-2013/Presentations/...3 Speaker Profile Patrick Baumgartner • Senior Software Consultant |](https://reader031.fdocuments.net/reader031/viewer/2022022512/5ae5777f7f8b9a6d4f8b54cc/html5/thumbnails/43.jpg)
43
Thank you!
Patrick Baumgartner, @patbaumgartner patrick.baumgartner [at] swiftmind [dot] com http://www.swiftmind.com @swiftmind