The US Navy needed a new Content Management System, but had already developed several great applications and had an investment in Spring. Could they bring it all together?
During this webinar, you will learn how Campbell Ewald (Navy's digital agency) used Magnolia's Blossom module for straightforward app integration and how Blossom enabled Spring developers to work efficiently with Magnolia CMS right from the start.
This Webinar is for Spring Developers of all levels, as well as Developers and IT professionals interested in application integration for business solutions.
2. CAMPBELL
EWALD
ABOUT THE WEBINAR
Posting Questions
Viewing the recorded
webinar and related
materials
Contacting Us
Tweeting - use hash tags:
#magnolia_cms #campbellewald
#springframework #springmvc
#USNavy
2 WEBINAR
3. CAMPBELL
EWALD
ABOUT US
MATT
DERTINGER
SOLUTIONS
ARCHITECT,
INTERACTIVE
R&D,
CE
DETROIT
CAMPBELL
EWALD
Twi9er:
@ma9nolia
SEAN
MCMAINS
SALES
ENGINEER
MAGNOLIA
CMS
sean.mcmains@magnolia-‐CMS.com
TOBIAS
MATTSSON
SENIOR
SOFTWARE
ENGINEER
&
BLOSSOM
DEVELOPER
MAGNOLIA
CMS
tobias.ma9sson@magnolia-‐cms.com
3 WEBINAR
4. CAMPBELL
EWALD
ABOUT CAMPBELL EWALD AND MAGNOLIA
CAMPBELL EWALD
Digital Agency
Magnolia Partner
General Motors, Kaiser Permanente, US Postal Service
Magnolia
Java-based Content Management System
Community and Enterprise Editions
Sony, Deloitte, Airbus and JBoss
4 WEBINAR
5. CAMPBELL
EWALD
WHAT WE’LL TALK ABOUT
Overview of Magnolia Blossom module
Navy Use Cases
Step-by-Step Walkthrough
Questions
5 WEBINAR
7. CAMPBELL
EWALD
A LITTLE PHILOSOPHY
The idea that sparked me writing the Blossom Module
for Magnolia CMS was to bring the CMS and
especially the content into Spring Web MVC not the
other way around. Controllers should be the building
blocks when composing pages.
– Tobias Mattsson
http://tobias-mattsson-magnolia.blogspot.com/2011/03/spring-web-mvc-with-content.html
7 WEBINAR
8. CAMPBELL
EWALD
WHAT’S BLOSSOM
Spring integration module for Magnolia
CMS
Spring Web MVC with Content
Key features:
Annotation based API
Spring controllers exposed as template
components
Pre-execution of template components
8 WEBINAR
9. CAMPBELL
EWALD
WHY USE BLOSSOM
Leverages proven Spring Framework
Easily integrate or migrate existing Spring-based applications
Spring developers will feel right at home
Dynamic dialogs,Virtual URI Mappings, Pre-execution
Easily access content in controllers
Best practice web app design patterns (MVC, IoC, AOP)
Open Source and Free to download and use
9 WEBINAR
11. CAMPBELL
EWALD
ABOUT NAVY.COM
Official recruitment Website for
the U.S. Navy
Redesigned in 2010, moved to
Magnolia CMS
Application integration for
subscription services, CRUD
functionality and user-space
applications
11 WEBINAR
12. CAMPBELL
EWALD
BLOSSOM + RESTEASY
Navy.com
Navy Custom Module
RESTEasy provided nice
Blossom JAX-RS client
Aligned with Magnolia CMS
roadmap
Navy Web Service Registry Allowed business
Business Component 1 Business Component 3 components to be loosely-
Business Component 2 Business Component n
coupled to CMS
12 WEBINAR
13. CAMPBELL
EWALD
BLOSSOM EXAMPLES
Request More Information (Lead) Forms
Find a Recruiter
Subscriber
Life Ops
Reserve Pay Calculator
Training Locations Map
Poll
13 WEBINAR
14. CAMPBELL
EWALD
FIND A RECRUITER
Finds the nearest Enlisted and Officer
Recruiter Locations based on the postal
code entered by the site visitor
Collect and validate input, call Navy Web
Service, display results.
14 WEBINAR
15. CAMPBELL
EWALD
LIFE OPS
Personality Profile Test to help
potential recruits plan their
future
Wizard type interface
Collect and validate selected
options from site visitor, populate
model, then calculate and display
results
15 WEBINAR
16. CAMPBELL
EWALD
STANDARD TEMPLATING KIT
The STK is a production-
ready website construction
framework.
• Best Practices
• Rapid Prototyping
• Modular Architecture
• Extensible
• Standards-Compliant
16 WEBINAR
18. CAMPBELL
EWALD
GETTING STARTED
Starting Spring - Add the Blossom Servlet Context Listener to your web.xml
<listener>
<listener-class>info.magnolia.module.blossom.support.ServletContextExposingContextListener</listener-class>
</listener>
Create a module for your custom Spring application components, quickest way:
$ mvn archetype:generate -DarchetypeCatalog=http://nexus.magnolia-cms.com/content/groups/public/
Have your module class extend BlossomModuleSupport and implement start and stop
methods:
public class BlossomSampleModule extends BlossomModuleSupport implements ModuleLifecycle {
public void start(ModuleLifecycleContext moduleLifecycleContext) {
initRootWebApplicationContext("classpath:/applicationContext.xml");
initBlossomDispatcherServlet("blossom", "classpath:/blossom-servlet.xml");
}
public void stop(ModuleLifecycleContext moduleLifecycleContext) {
destroyDispatcherServlets();
closeRootWebApplicationContext();
}
}
18 WEBINAR
19. CAMPBELL
EWALD
SPRING BEAN CONFIGURATION
Create a Spring bean config file called applicationContext.xml
<?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:blossom="http://www.magnolia-cms.com/schema/blossom"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.magnolia-cms.com/schema/blossom http://www.magnolia-cms.com/schema/blossom-1.2.xsd">
<blossom:configuration />
</beans>
19 WEBINAR
26. CAMPBELL
EWALD
LIFE OPS SPRING VALIDATOR
public class LifeOpsValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return LifeOps.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
LifeOps lifeOps = (LifeOps) target;
if (lifeOps.getActivities() == null || lifeOps.getActivities().length == 0) {
errors.rejectValue("activities", "activities.required", "Please choose at least one activity before proceeding.");
}
if (lifeOps.getInterests() == null || lifeOps.getInterests().length == 0) {
errors.rejectValue("interests", "interests.required", "Please choose at least one interest before proceeding.");
}
if (lifeOps.getCareers() == null || lifeOps.getCareers().length == 0) {
errors.rejectValue("careers", "careers.required", "Please choose at least one career before proceeding.");
}
}
}
26 WEBINAR
27. CAMPBELL
EWALD
LIFE OPS CONTROLLER
@Controller
@RequestMapping("/life-ops")
@Paragraph("Life Ops form")
@ParagraphDescription("Adds a Life Ops form and displays Life Ops Results")
@I18nBasename("com.c_e.webinar.magnolia.module.blossomsample.messages")
public class LifeOpsController {
private static final Logger log = LoggerFactory.getLogger(LifeOpsController.class);
private final String LIFE_OPS_FORM_PATH = "life-ops/form";
private final String LIFE_OPS_SHOW_PATH = "life-ops/show";
@Autowired
private Validator validator;
@RequestMapping(method = RequestMethod.GET)
public String form(LifeOps lifeOps) {
return LIFE_OPS_FORM_PATH;
}
...
}
27 WEBINAR
30. CAMPBELL
EWALD
LIFE OPS CONTROLLER
@TabFactory("Settings")
public void addTab(TabBuilder builder) {
builder.addEdit("activitiesText", "Activities Text", "A short description for the activities fieldset");
builder.addEdit("interestsText", "Interests Text", "A short description for the interests fieldset");
builder.addEdit("careersText", "Careers Text", "A short description for the interests fieldset");
builder.addFckEditor("resultsText", "Results Text", "A short intro for the results page");
}
30 WEBINAR
31. CAMPBELL
EWALD
LIFE OPS VIRTUAL URI MAPPING
@VirtualURIMapper
public class LifeOpsURIMapper {
private Pattern pattern;
public LifeOpsURIMapper() {
this.pattern = Pattern.compile("^/life-ops/results/([0-1]?[0-8])/([0-1]?[0-8])/([0-1]?[0-8])/([0-1]?[0-8])/([0-1]?
[0-8])/([0-1]?[0-8])/?");
}
public String mapping(String uri, HttpServletRequest request) {
this.pattern = Pattern.compile("^/(" + STKUtil.getSite().getName()
+ "/)?life-ops/results/([0-1]?[0-8])/([0-1]?[0-8])/([0-1]?[0-8])/([0-1]?[0-8])/([0-1]?[0-8])/([0-1]?
[0-8])/?");
Matcher matcher = pattern.matcher(uri);
if (matcher.matches()) {
return matcher.replaceAll("forward:/" + STKUtil.getSite().getName()
+ "/life-ops/results/?advisor=$2&doer=$3&innovator=$4&persuader=$5&planner=$6&problemSolver=$7");
}
return null;
}
}
31 WEBINAR
32. CAMPBELL
EWALD
LIFE OPS FORM VIEW
[#assign cms=JspTaglibs["cms-taglib"]]
[#assign form=JspTaglibs["http://www.springframework.org/tags/form"]]
<div>
[@cms.editBar /]
[@form.form id="life-ops-form" modelAttribute="lifeOps"]
...
<fieldset>
<legend>Activities</legend>
...
<dl class="prop">
<dt><span>What do you like to do?</span></dt>
<dd class="value">
<ul>
<li>
<input id="activities1" name="activities" value="D" type="checkbox" />
<label for="activities1"><strong>Set up a home computer network</strong></label>
</li>
<li>
<input id="activities2" name="activities" value="S" type="checkbox" />
<label for="activities2"><strong>Track the path of a hurricane</strong></label>
</li>
...
</ul>
</dd>
</dl>
</fieldset>
32 WEBINAR
36. CAMPBELL
EWALD
CONTACT INFO
MATT
DERTINGER
SOLUTIONS
ARCHITECT,
INTERACTIVE
R&D,
CE
DETROIT
CAMPBELL
EWALD
Twi9er:
@ma9nolia
SEAN
MCMAINS
SALES
ENGINEER
MAGNOLIA
CMS
sean.mcmains@magnolia-‐cms.com
TOBIAS
MATTSSON
SENIOR
SOFTWARE
ENGINEER
&
BLOSSOM
DEVELOPER
MAGNOLIA
CMS
tobias.ma9sson@magnolia-‐cms.com
36 WEBINAR
37. CAMPBELL
EWALD
FURTHER READING
Visit the Magnolia documentation site to download Magnolia and find tutorials and guides
http://documentation.magnolia-cms.com/index.html
The Blossom reference documentation
http://documentation.magnolia-cms.com/modules/blossom.html
Blossom Sample Webapp
http://documentation.magnolia-cms.com/modules/blossom.html#GettingStarted
Tobias Mattsson's blog
http://tobias-mattsson-magnolia.blogspot.com/
Ask your questions and see what others are doing at the Magnolia community forum
http://forum.magnolia-cms.com/forum.html
37 WEBINAR