Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
!1
Blossom in the Real World
Sr. Software Engineer, Magnolia
Lead developer of Blossom Module
Spring Framework user since 2005
Tobias Mattsson
2@sigget
3
Jan Haderka
Head of Support, Magnolia
@rah003
4
Casey Dement
VP of Architecture, Sharecare
@casey_dement
#Mplify
5
Magnolia + Spring = Blossom 6
@Template
7
TEMPLATEREQUEST CONTENT
CMS
8
TEMPLATEREQUEST CONTENT
CMS + Blossom
9
CONTROLLER
MODEL
VIEW
Page Template
@Controller
@Template(id="myModule:pages/main", title="Main")
public class MainTemplate {
!
   @RequestMappi...
11
PAGE
PAGES CONTAIN 0:n AREAS
12
PAGE
AREA
A
R
E
A
AREA
PAGES CONTAIN 0:n AREAS
13
PAGE
AREA
A
R
E
A
AREA
AREAS HAVE 0:n COMPONENTS
COMPONENT
COMPONENT
Etiam porta sem malesuada ...
Area Template
@Controller
@Template(id="myModule:pages/main",title="Main Template")
public class MainTemplate {
   @Contro...
Component Template
@Controller
@Template(id="myModule:components/shoppingCart",
         title="Shopping Cart")
@TemplateD...
SERVLET
CONTAINER
RENDERING
FILTER
RENDERING
ENGINE
BLOSSOM
DISPATCHER
SERVLET
CONTROLLER
16
How Blossom Works
Blossom 3.0
17
What’s new?
Blossom 3.0
18
Update for Magnolia 5 series
Requires Magnolia 5.1
new ways of building dialogs
availability annotation
19
Dialogs
Fluent Builder-style API
!
@TabFactory("Content")
public void contentTab(UiConfig cfg, TabBuilder tab) {
tab.fields(
cfg.fiel...
Dialogs and the Class Hierarchy
public abstract class BasePageTemplate {

@TabFactory("Meta")

public void metaTab(UiConfig...
Input Validation
...
public void contentTab(UiConfig cfg, TabBuilder tab) {
tab.fields(
cfg.fields.text("name").label("Name")...
Dynamic Dialog
!
!
@Template(id="myModule:components/bookCategory", title="Book category")
@TemplateDescription("A list of...
Dynamic Dialog
!
@Template(id="myModule:components/bookCategory", title="Book category")
@TemplateDescription("A list of b...
@AvailableComponentClasses
25
Components Availability
!
   @ComponentCategory

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)
public @in...
@More
27
Content, content, more content
!
@Template(id="myModule:components/bookCategory", title="Book category")
@TemplateDescript...
Now The Real World 29
Thank You!
30
31
magnolia-cms.com/spring
32
How do I get started on my project?
33
mvn archetype:generate -DarchetypeCatalog=http://nexus.magnolia-cms.com/
content/groups/public/
!
choose magnolia-blossom-...
How would I build a REST interface to my CMS
content using Blossom?
35
REST servlet in module descriptor
<servlets>
  <servlet>
    <name>rest</name>
    <class>org.springframework.web.servlet....
REST Controller
@Controller
public class ProductsRestController {
!
@RequestMapping("/products/{productId}")
public Produc...
Can I leverage Magnolia's caching functionality
to improve the performance of my Spring app?
38
Influencing caching 39
@Controller
@Template(title="Text", id="myModule:components/text")
public class TextComponent {
!
@...
How can I present dialogs in different languages
using Blossom?
40
!
@Controller
@Template(title = "Text", id = "blossomSampleModule:components/text")
@I18nBasename("info.magnolia.blossom.s...
!
!
/info/magnolia/blossom/sample/messages_en.properties
textComponent.contentTab.label = Content
textComponent.contentTab...
How do I migrate my existing site to Magnolia/
Blossom?
43
How can I integrate Spring Security?
44
45
How can I dependency inject spring beans into
RenderingModels?
46
Autowired RenderingModel
public class MyRenderingModel extends RenderingModelImpl<TemplateDefinition> {
!
@Autowired
privat...
Autowired RenderingModel
!
public class MyRenderingModel extends AbstractAutowiredRenderingModel<TemplateDefinition> {
!
@A...
Views 49
Rendering an Area
FreeMarker
[@cms.area name="main" /]
!
JSP
<cms:area name="main" />
50
Rendering Components in an Area
FreeMarker
[#list components as component]
   [@cms.component content=component /]
[/#list...
Page Template Availability
@Controller

@Template(title="Article", id="myModule:/pages/article")

public class ArticleTemp...
Available Components
@Controller
@Area("promos")
@AvailableComponentClasses({TextComponent.class,
                        ...
Area Inheritance
@Controller
@Area("promos")
@Inherits
@AvailableComponentClasses({TextComponent.class,
                  ...
Form Submission
/* Standard annotations omitted */
public class ContactFormComponent {

@RequestMapping(value="/contact", ...
But wait a minute …
56
Caused by: org.springframework.web.util.NestedServletException: Reques

 at org.springframework.web...
Controller Pre-execution
57
C M V
PAGE
C M V
Area
C M V
Component
C M V
Component
C M V
Component
C
CPE Implementation 58
Code in View
<form>
<blossom:pecid-input />
<input type=”text” name=”email” />
...
!
HTML Output
<fo...
Spring Web MVC
+
Content
59
Spring Web Flow
60
REQUEST LANDING
PAGE
SPRING
WEB FLOW
Spring Web Flow
61
REQUEST LANDING
PAGE
FORM
SUBMIT?
SPRING
WEB FLOW
62
Trademarks
Other trademarks are the property of their respective owners.
Magnolia
The Pulse are trademarks of
Magnolia ...
Upcoming SlideShare
Loading in …5
×

Getting Healthy with Magnolia, Blossom and Spring

2,563 views

Published on

This presentation was given at Amplify Miami 2014 by Jan Haderka, Senior Developer at Magnolia International, and Casey Dement, VP of Architecture at Sharecare, Inc.

Casey showed how Sharecare integrated Magnolia and Blossom with Spring MVC and Akamai to build a highly flexible and scalable website. Jan gives an introduction and an update on the new features in Blossom 3.

Published in: Technology
  • DOWNLOAD THIS BOOKS INTO AVAILABLE FORMAT (2019 Update) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { https://soo.gd/irt2 } ......................................................................................................................... Download Full EPUB Ebook here { https://soo.gd/irt2 } ......................................................................................................................... Download Full doc Ebook here { https://soo.gd/irt2 } ......................................................................................................................... Download PDF EBOOK here { https://soo.gd/irt2 } ......................................................................................................................... Download EPUB Ebook here { https://soo.gd/irt2 } ......................................................................................................................... Download doc Ebook here { https://soo.gd/irt2 } ......................................................................................................................... ......................................................................................................................... ................................................................................................................................... eBook is an electronic version of a traditional print book THIS can be read by using a personal computer or by using an eBook reader. (An eBook reader can be a software application for use on a computer such as Microsoft's free Reader application, or a book-sized computer THIS is used solely as a reading device such as Nuvomedia's Rocket eBook.) Users can purchase an eBook on diskette or CD, but the most popular method of getting an eBook is to purchase a downloadable file of the eBook (or other reading material) from a Web site (such as Barnes and Noble) to be read from the user's computer or reading device. Generally, an eBook can be downloaded in five minutes or less ......................................................................................................................... .............. Browse by Genre Available eBooks .............................................................................................................................. Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, ......................................................................................................................... ......................................................................................................................... .....BEST SELLER FOR EBOOK RECOMMEND............................................................. ......................................................................................................................... Blowout: Corrupted Democracy, Rogue State Russia, and the Richest, Most Destructive Industry on Earth,-- The Ride of a Lifetime: Lessons Learned from 15 Years as CEO of the Walt Disney Company,-- Call Sign Chaos: Learning to Lead,-- StrengthsFinder 2.0,-- Stillness Is the Key,-- She Said: Breaking the Sexual Harassment Story THIS Helped Ignite a Movement,-- Atomic Habits: An Easy &amp; Proven Way to Build Good Habits &amp; Break Bad Ones,-- Everything Is Figureoutable,-- What It Takes: Lessons in the Pursuit of Excellence,-- Rich Dad Poor Dad: What the Rich Teach Their Kids About Money THIS the Poor and Middle Class Do Not!,-- The Total Money Makeover: Classic Edition: A Proven Plan for Financial Fitness,-- Shut Up and Listen!: Hard Business Truths THIS Will Help You Succeed, ......................................................................................................................... .........................................................................................................................
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • 11:11 - A Message From The Universe? People all of the world keep seeing the repeating numbers "11:11." Discover the POWERFUL guidance the Universe wants everyone to know! ♣♣♣ http://scamcb.com/manifmagic/pdf
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • The "Magical" Transformation That Happens When You Combine Two Of The Best Brain Reprogramming Technologies ➤➤ https://bit.ly/30Ju5r6
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Getting Healthy with Magnolia, Blossom and Spring

  1. 1. !1 Blossom in the Real World
  2. 2. Sr. Software Engineer, Magnolia Lead developer of Blossom Module Spring Framework user since 2005 Tobias Mattsson 2@sigget
  3. 3. 3 Jan Haderka Head of Support, Magnolia @rah003
  4. 4. 4 Casey Dement VP of Architecture, Sharecare @casey_dement
  5. 5. #Mplify 5
  6. 6. Magnolia + Spring = Blossom 6
  7. 7. @Template 7
  8. 8. TEMPLATEREQUEST CONTENT CMS 8
  9. 9. TEMPLATEREQUEST CONTENT CMS + Blossom 9 CONTROLLER MODEL VIEW
  10. 10. Page Template @Controller @Template(id="myModule:pages/main", title="Main") public class MainTemplate { !    @RequestMapping("/main")    public String render(ModelMap model) {        return "pages/main";    } } 10
  11. 11. 11 PAGE
  12. 12. PAGES CONTAIN 0:n AREAS 12 PAGE AREA A R E A AREA
  13. 13. PAGES CONTAIN 0:n AREAS 13 PAGE AREA A R E A AREA AREAS HAVE 0:n COMPONENTS COMPONENT COMPONENT Etiam porta sem malesuada magna mollis euismod. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. COMPONENT Etiam porta sem malesuada magna mollis euismod. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed posuere consectetur est at lobortis. C O M P O N E N T
  14. 14. Area Template @Controller @Template(id="myModule:pages/main",title="Main Template") public class MainTemplate {    @Controller   @Area("main")    public static class MainArea {        @RequestMapping("/main/mainArea")        public String render() {            return "areas/main";        }    ... 14
  15. 15. Component Template @Controller @Template(id="myModule:components/shoppingCart",          title="Shopping Cart") @TemplateDescription("Shopping cart") public class ShoppingCartComponent {    @RequestMapping("/shoppingCart")    public String handleRequest() {        ...        return "components/shoppingCart";    } ... 15
  16. 16. SERVLET CONTAINER RENDERING FILTER RENDERING ENGINE BLOSSOM DISPATCHER SERVLET CONTROLLER 16 How Blossom Works
  17. 17. Blossom 3.0 17 What’s new?
  18. 18. Blossom 3.0 18 Update for Magnolia 5 series Requires Magnolia 5.1 new ways of building dialogs availability annotation
  19. 19. 19 Dialogs
  20. 20. Fluent Builder-style API ! @TabFactory("Content") public void contentTab(UiConfig cfg, TabBuilder tab) { tab.fields( cfg.fields.text("heading").label("Heading"),
 cfg.fields.richText("body").label("Text body"),
 cfg.fields.websiteLink("categoryLink").label("Link"),
 cfg.fields.basicUpload("image").label("Image"),
 cfg.fields.checkbox("inlineImage").label("Inline Image")  );
 } 20
  21. 21. Dialogs and the Class Hierarchy public abstract class BasePageTemplate {
 @TabFactory("Meta")
 public void metaTab(UiConfig cfg, TabBuilder tab) {
 tab.fields( cfg.fields.text("metaAuthor").label("Author"),
     cfg.fields.text("metaKeywords").label("Keywords"),
     cfg.fields.text("metaDescription").label("Description")    );
  }
 } 21
  22. 22. Input Validation ... public void contentTab(UiConfig cfg, TabBuilder tab) { tab.fields( cfg.fields.text("name").label("Name").required(), cfg.fields.text("email").label("Email") .validator(cfg.validators.email()) ); } ... 22
  23. 23. Dynamic Dialog ! ! @Template(id="myModule:components/bookCategory", title="Book category") @TemplateDescription("A list of books in a given category.") @Controller public class BookCategoryComponent {
    @Autowired
    private SalesApplicationWebService service;
 
    @RequestMapping("/bookcategory")
    public String render(Node content, ModelMap model) throws RepositoryException {
        String category = content.getProperty("category").getString();
        model.put("books", service.getBooksInCategory(category));
        return "components/bookCategory";
    } @TabFactory("Content")
    public void contentTab(UiConfig cfg, TabBuilder tab) {
        Collection<String> categories = service.getBookCategories();
        tab.fields(
 cfg.fields.select("category").label("Category").options(categories)
        );
    } } 23
  24. 24. Dynamic Dialog ! @Template(id="myModule:components/bookCategory", title="Book category") @TemplateDescription("A list of books in a given category.") @Controller public class BookCategoryComponent {
    @Autowired
    private SalesApplicationWebService service;
 
    @RequestMapping("/bookcategory")
    public String render(Node content, ModelMap model) throws RepositoryException {
        String category = content.getProperty("category").getString();
        model.put("books", service.getBooksInCategory(category));
        return "components/bookCategory";
    } @TabFactory("Content")
    public void contentTab(UiConfig cfg, TabBuilder tab) {
        Collection<String> categories = service.getBookCategories();
        tab.fields(
 cfg.fields.select("category").label("Category").options(categories)
        );
    } } 24
  25. 25. @AvailableComponentClasses 25
  26. 26. Components Availability !    @ComponentCategory
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.TYPE) public @interface Banner { } ! @Area("banners") @AvailableComponentClasses({Banner.class}) @Controller    public class BannersArea { … } ! @Banner @Template(id="myModule:components/largePromoBanner"), title="Large banner”) @Controller("banner")    public class LargePromoBannerComponent { …
     } 26
  27. 27. @More 27
  28. 28. Content, content, more content ! @Template(id="myModule:components/bookCategory", title="Book category") @TemplateDescription("A list of books in a given category.") @Controller public class BookCategoryComponent {
    @Autowired
    private SalesApplicationWebService service;
 
    @RequestMapping("/bookcategory")    public String render(Node content, ModelMap model) throws RepositoryException {
        String category = content.getProperty("category").getString();        model.put("books", service.getBooksInCategory(category));
        return "components/bookCategory";
    } @TabFactory("Content")
    public void contentTab(UiConfig cfg, TabBuilder tab) {
        Collection<String> categories = service.getBookCategories();
        tab.fields(
 cfg.fields.select("category").label("Category").options(categories)
        );
    } } 28
  29. 29. Now The Real World 29
  30. 30. Thank You! 30
  31. 31. 31 magnolia-cms.com/spring
  32. 32. 32
  33. 33. How do I get started on my project? 33
  34. 34. mvn archetype:generate -DarchetypeCatalog=http://nexus.magnolia-cms.com/ content/groups/public/ ! choose magnolia-blossom-module-archetype ! Define value for property 'groupId': : com.acme Define value for property 'artifactId': : acme-module Define value for property 'version': 1.0-SNAPSHOT: Define value for property 'package': com.acme: Define value for property 'magnolia-version': : 4.5.11 Define value for property 'module-class-name': : AcmeModule Define value for property 'module-name': acme-module: acmeModule ! ! ! ! http://wiki.magnolia-cms.com/display/WIKI/ Creating+a+new+Blossom+project+using+maven+archetypes
  35. 35. How would I build a REST interface to my CMS content using Blossom? 35
  36. 36. REST servlet in module descriptor <servlets>   <servlet>     <name>rest</name>     <class>org.springframework.web.servlet.DispatcherServlet</class>     <mappings>       <mapping>/rest/*</mapping>     </mappings>     <params>       <param>         <name>contextConfigLocation</name>         <value>classpath:/rest-servlet.xml</value>       </param>     </params>   </servlet> </servlets> 36
  37. 37. REST Controller @Controller public class ProductsRestController { ! @RequestMapping("/products/{productId}") public Product findProduct(@PathVariable String productId) { // implementation omitted } } 37
  38. 38. Can I leverage Magnolia's caching functionality to improve the performance of my Spring app? 38
  39. 39. Influencing caching 39 @Controller @Template(title="Text", id="myModule:components/text") public class TextComponent { ! @RequestMapping("/text") public String render(HttpResponse response) { response.setHeader("Cache-Control", "no-cache"); return "components/text.jsp"; } }
  40. 40. How can I present dialogs in different languages using Blossom? 40
  41. 41. ! @Controller @Template(title = "Text", id = "blossomSampleModule:components/text") @I18nBasename("info.magnolia.blossom.sample.messages") public class TextComponent { ! @TabFactory("textComponent.contentTab.label") public void contentTab(UiConfig cfg, TabBuilder tab) { tab.fields( cfg.fields.text("heading").label("textComponent.contentTab.heading") ); } } 41I18n Blossom Dialog
  42. 42. ! ! /info/magnolia/blossom/sample/messages_en.properties textComponent.contentTab.label = Content textComponent.contentTab.heading = Heading ! ! ! /info/magnolia/blossom/sample/messages_sv.properties textComponent.contentTab.label = Innehåll textComponent.contentTab.heading = Rubrik ! 42I18n Blossom Dialog
  43. 43. How do I migrate my existing site to Magnolia/ Blossom? 43
  44. 44. How can I integrate Spring Security? 44
  45. 45. 45
  46. 46. How can I dependency inject spring beans into RenderingModels? 46
  47. 47. Autowired RenderingModel public class MyRenderingModel extends RenderingModelImpl<TemplateDefinition> { ! @Autowired private MyService service; ! public MyRenderingModel(ServletContext servletContext, Node content, TemplateDefinition definition, RenderingModel<?> p super(content, definition, parent); WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(servletContext); AutowireCapableBeanFactory beanFactory = wac.getAutowireCapableBeanFactory(); beanFactory.autowireBean(this); } 47
  48. 48. Autowired RenderingModel ! public class MyRenderingModel extends AbstractAutowiredRenderingModel<TemplateDefinition> { ! @Autowired private MyService service; ! public MyRenderingModel(ServletContext servletContext, Node content, TemplateDefinition definition, RenderingModel<?> super(content, definition, parent, servletContext); } ! ! ! ! 48
  49. 49. Views 49
  50. 50. Rendering an Area FreeMarker [@cms.area name="main" /] ! JSP <cms:area name="main" /> 50
  51. 51. Rendering Components in an Area FreeMarker [#list components as component]    [@cms.component content=component /] [/#list] ! JSP <c:forEach items="${components}" var="component">
    <cms:component content="${component}" />
 </c:forEach> 51
  52. 52. Page Template Availability @Controller
 @Template(title="Article", id="myModule:/pages/article")
 public class ArticleTemplate {    ...    @Available
    public boolean isAvailable(Node node) {
        return node.getPath().startsWith("/articles/");
    } } 52
  53. 53. Available Components @Controller @Area("promos") @AvailableComponentClasses({TextComponent.class,                            ShoppingCartComponent.class}) public static class PromosArea {    @RequestMapping("/main/promos")    public String render() {        return "areas/promos";    } } 53
  54. 54. Area Inheritance @Controller @Area("promos") @Inherits @AvailableComponentClasses({TextComponent.class,                            ShoppingCartComponent.class}) public static class PromosArea {    @RequestMapping("/main/promos")    public String render() {        return "areas/promos";    } } 54
  55. 55. Form Submission /* Standard annotations omitted */ public class ContactFormComponent {
 @RequestMapping(value="/contact", method=RequestMethod.GET)
  public String viewForm(@ModelAttribute ContactForm contactForm) {
 return "components/contactForm"; } @RequestMapping(value="/contact", method=RequestMethod.POST)
 public String handleSubmit(@ModelAttribute ContactForm contactForm, BindingResult result) { new ContactFormValidator().validate(contactForm, result); if (result.hasErrors()) { return "components/contactForm";
 } return "redirect:/home/contact/thankyou.html"; }
 55
  56. 56. But wait a minute … 56 Caused by: org.springframework.web.util.NestedServletException: Reques at org.springframework.web.servlet.FrameworkServlet.processRequest( at org.springframework.web.servlet.FrameworkServlet.doGet(Framewor at javax.servlet.http.HttpServlet.service(HttpServlet.java:617) at info.magnolia.module.blossom.render.BlossomDispatcherServlet.forw at info.magnolia.module.blossom.render.BlossomTemplateRenderer.ren ... 92 more Caused by: java.lang.IllegalStateException at org.apache.catalina.connector.ResponseFacade.sendRedirect(Respons … the response has been sent.
  57. 57. Controller Pre-execution 57 C M V PAGE C M V Area C M V Component C M V Component C M V Component C
  58. 58. CPE Implementation 58 Code in View <form> <blossom:pecid-input /> <input type=”text” name=”email” /> ... ! HTML Output <form> <input type=”hidden” name=”_pecid” value=”ff6cefa6-d958-47b1-af70-c82a414f17e1” /> <input type=”text” name=”email” /> ...
  59. 59. Spring Web MVC + Content 59
  60. 60. Spring Web Flow 60 REQUEST LANDING PAGE SPRING WEB FLOW
  61. 61. Spring Web Flow 61 REQUEST LANDING PAGE FORM SUBMIT? SPRING WEB FLOW
  62. 62. 62 Trademarks Other trademarks are the property of their respective owners. Magnolia The Pulse are trademarks of Magnolia International Limited.}

×