Magnolia blossom-webinar
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Magnolia blossom-webinar

on

  • 1,679 views

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?...

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.

Statistics

Views

Total Views
1,679
Views on SlideShare
1,577
Embed Views
102

Actions

Likes
3
Downloads
19
Comments
0

4 Embeds 102

http://www.magnolia-cms.com 77
http://localhost 17
http://website-test.magnolia-cms.com 7
http://author.magnolia-cms.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Magnolia blossom-webinar Presentation Transcript

  • 1. US NAVY INTEGRATES SPRING APPS WITH FLYING COLORS THANKS TO WEB CMS +
  • 2. CAMPBELL EWALDABOUT 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 EWALDABOUT 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 EWALDABOUT 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 EWALDWHAT WE’LL TALK ABOUT Overview of Magnolia Blossom module Navy Use Cases Step-by-Step Walkthrough Questions 5 WEBINAR
  • 6. CAMPBELLEWALD BLOSSOM OVERVIEW 6 WEBINAR
  • 7. CAMPBELL EWALDA 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 EWALDWHAT’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 EWALDWHY 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
  • 10. CAMPBELLEWALD NAVY USE CASES TM 10 WEBINAR
  • 11. CAMPBELL EWALDABOUT 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 EWALDBLOSSOM + RESTEASY Navy.com Navy Custom Module RESTEasy provided niceBlossom 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 EWALDBLOSSOM EXAMPLES Request More Information (Lead) Forms Find a Recruiter Subscriber Life Ops Reserve Pay Calculator Training Locations Map Poll 13 WEBINAR
  • 14. CAMPBELL EWALDFIND 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 EWALDLIFE 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 EWALDSTANDARD TEMPLATING KIT The STK is a production- ready website construction framework. • Best Practices • Rapid Prototyping • Modular Architecture • Extensible • Standards-Compliant 16 WEBINAR
  • 17. CAMPBELL EWALDBUILDING LIFE OPS: STEP-BY-STEP 17 WEBINAR
  • 18. CAMPBELL EWALDGETTING 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 EWALDSPRING 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
  • 20. CAMPBELL EWALDSPRING BEAN CONFIGURATION Create a Spring bean config file called blossom-servlet.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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="..."> <context:annotation-config /> <context:component-scan base-package="com.c_e.webinar.magnolia.module.blossomsample" use-default-filters="false"> <context:include-filter type="annotation" expression="info.magnolia.module.blossom.annotation.Paragraph" /> <context:include-filter type="annotation" expression="info.magnolia.module.blossom.annotation.Template" /> <context:include-filter type="annotation" expression="info.magnolia.module.blossom.annotation.DialogFactory" /> <context:include-filter type="annotation" expression="info.magnolia.module.blossom.annotation.VirtualURIMapper" /> <context:include-filter type="assignable" expression="info.magnolia.cms.beans.config.VirtualURIMapping" /> </context:component-scan> ... </beans> 20 WEBINAR
  • 21. CAMPBELL EWALDSPRING BEAN CONFIGURATION Add Spring Handler Adapters and Mappings to blossom-servlet.xml <?xml version="1.0" encoding="UTF-8"?> <beans ...> ... <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" /> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="customArgumentResolver"> <bean class="info.magnolia.module.blossom.web.BlossomWebArgumentResolver" /> </property> </bean> <bean class="info.magnolia.module.blossom.preexecution.BlossomHandlerMapping"> <property name="targetHandlerMappings"> <list> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="useDefaultSuffixPattern" value="false" /> </bean> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" /> </list> </property> </bean> ... </beans> 21 WEBINAR
  • 22. CAMPBELL EWALDSPRING BEAN CONFIGURATION Add Spring View Resolvers to blossom-servlet.xml <?xml version="1.0" encoding="UTF-8"?> <beans...> ... <bean class="info.magnolia.module.blossom.view.UuidRedirectViewResolver"> <property name="order" name="1" /> </bean> <bean class="info.magnolia.module.blossom.view.TemplateViewResolver"> <property name="order" name="2" /> <property name="prefix" name="/ce-webinar-templating-kit/templates/blossomsamples" /> <property name="suffix" name=".ftl" /> <property name="viewRenderer"> <bean class="info.magnolia.module.blossom.view.FreemarkerTemplateViewRenderer" /> </property> </bean> <bean class="info.magnolia.module.blossom.view.ParagraphViewResolver"> <property name="order" name="3" /> <property name="prefix" name="/ce-webinar-templating-kit/paragraphs/blossomsamples" /> <property name="suffix" name=".ftl" /> <property name="viewRenderer"> <bean class="info.magnolia.module.blossom.view.FreemarkerParagraphViewRenderer" /> </property> </bean> </beans> 22 WEBINAR
  • 23. CAMPBELL EWALDLIFE OPS MODEL Uses Bean Validation API (JSR 303) Excerpt: public class LifeOps implements Serializable { ... @NotNull @Min(0) @Max(18) private Integer advisor; ... @NotNull @Min(0) @Max(18) private Integer doer; ... } 23 WEBINAR
  • 24. CAMPBELL EWALDLIFE OPS MODEL Add in bean validation support to blossom-servlet.xml <?xml version="1.0" encoding="UTF-8"?> <beans ...> ... <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> ... <property name="webBindingInitializer"> <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"> <property name="validator" ref="validator" /> </bean> </property> </bean> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" /> ... </beans> 24 WEBINAR
  • 25. CAMPBELL EWALDLIFE OPS MODEL Constructor public LifeOps(Integer advisor, Integer doer, Integer innovator, Integer persuader, Integer planner, Integer problemSolver) { this.advisor = advisor; this.doer = doer; this.innovator = innovator; this.persuader = persuader; this.planner = planner; this.problemSolver = problemSolver; } Constructor using transients: public LifeOps(String[] activities, String[] interests, String[] careers) { this.activities = activities; this.interests = interests; this.careers = careers; this.resetScores(); this.calculateScores(activities); this.calculateScores(interests); this.calculateScores(careers); } 25 WEBINAR
  • 26. CAMPBELL EWALDLIFE OPS SPRING VALIDATORpublic 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 EWALDLIFE 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
  • 28. CAMPBELL EWALDLIFE OPS CONTROLLER@RequestMapping(method = RequestMethod.POST)public String processSubmit(@Valid LifeOps lifeOps, BindingResult result, Model model) { new LifeOpsValidator().validate(lifeOps, result); if (result.hasErrors()) { List<FieldError> fieldErrors = result.getFieldErrors(); Map<String, String> errorsMap = new HashMap<String, String>(); for (int i = 0; i < fieldErrors.size(); i++) { FieldError thisError = fieldErrors.get(i); errorsMap.put(thisError.getField(), thisError.getDefaultMessage() ); } lifeOps.setErrors(errorsMap); model.addAttribute("lifeOps", lifeOps); return LIFE_OPS_FORM_PATH; } else { lifeOps = new LifeOps(lifeOps.getActivities(), lifeOps.getInterests(), lifeOps.getCareers() ); model.addAttribute("lifeOps", lifeOps); return "redirect:/" + STKUtil.getSite().getName() + "/life-ops/results" + "/" + lifeOps.getAdvisor() + "/" + lifeOps.getDoer() + "/" + lifeOps.getInnovator() + "/" + lifeOps.getPersuader() + "/" + lifeOps.getPlanner() + "/" + lifeOps.getProblemSolver(); }} 28 WEBINAR
  • 29. CAMPBELL EWALDLIFE OPS CONTROLLER@RequestMapping(method = RequestMethod.GET, params = "advisor")public String show( @RequestParam Integer advisor, @RequestParam Integer doer, @RequestParam Integer innovator, @RequestParam Integer persuader, @RequestParam Integer planner, @RequestParam Integer problemSolver, Model model) { try { LifeOps lifeOps = new LifeOps(advisor, doer, innovator, persuader, planner, problemSolver); model.addAttribute("lifeOps", lifeOps); } catch (Exception e) { log.error("LifeOpsController.show() Exception:" + e); } return LIFE_OPS_SHOW_PATH;} 29 WEBINAR
  • 30. CAMPBELL EWALDLIFE 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 EWALDLIFE OPS VIRTUAL URI MAPPING@VirtualURIMapperpublic 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 EWALDLIFE 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
  • 33. CAMPBELL EWALDLIFE OPS RESULTS VIEW[#assign results = [ {"name": "problemSolver", "label": "Problem Solver", "score": lifeOps.problemSolver}, {"name": "planner", "label": "Planner", "score": lifeOps.planner}, {"name": "persuader", "label": "Persuader", "score": lifeOps.persuader}, {"name": "innovator", "label": "Innovator", "score": lifeOps.innovator}, {"name": "doer", "label": "Do-er", "score": lifeOps.doer}, {"name": "advisor", "label": "Advisor", "score": lifeOps.advisor}]]... 33 WEBINAR
  • 34. CAMPBELL EWALDLIFE OPS RESULTS VIEW<div class="super-list"> [@cms.editBar /] <ul> [#list results?sort_by("score")?reverse as result] [#assign profileDivId = result.label?lower_case?trim?replace( , -)] [#assign scoreWidth = (result.score/2)*11+"%"] [#assign contentCollectionText = result.name + "Text"] [#assign contentCollectionExtras = result.name + "Extras"] <li> <h3> <a rel="bookmark" href="#${profileDivId}" title="${result.label}"> <dfn style="width:${scoreWidth};"><strong>${result.label}</strong></dfn> </a> </h3> ... [#if contentCollectionText?exists] [@cms.contentNodeIterator contentNodeCollectionName=contentCollectionText] [@cms.includeTemplate/] [/@cms.contentNodeIterator] [/#if] [@cms.newBar contentNodeCollectionName=contentCollectionText paragraph="stkTextImage, stkTeaserGroup" /] ... </li> [/#list] </ul></div><!-- end super-list --> 34 WEBINAR
  • 35. CAMPBELLEWALD QUESTIONS 35 WEBINAR
  • 36. CAMPBELL EWALDCONTACT 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 EWALDFURTHER 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 Mattssons 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