SlideShare a Scribd company logo
!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 {
!
   @RequestMapping("/main")
   public String render(ModelMap model) {
       return "pages/main";
   }
}
10
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 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
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
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
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.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
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
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
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
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
@AvailableComponentClasses
25
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
@More
27
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
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-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
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.DispatcherServlet</class>
    <mappings>
      <mapping>/rest/*</mapping>
    </mappings>
    <params>
      <param>
        <name>contextConfigLocation</name>
        <value>classpath:/rest-servlet.xml</value>
      </param>
    </params>
  </servlet>
</servlets>
36
REST Controller
@Controller
public class ProductsRestController {
!
@RequestMapping("/products/{productId}")
public Product findProduct(@PathVariable String productId) { 
// implementation omitted
}
}
37
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 {
!
@RequestMapping("/text")
public String render(HttpResponse response) {
response.setHeader("Cache-Control", "no-cache");
return "components/text.jsp";
}
}
How can I present dialogs in different languages
using Blossom?
40
!
@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
!
!
/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
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
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
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
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]
!
JSP
<c:forEach items="${components}" var="component">

   <cms:component content="${component}" />

</c:forEach>
51
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
Available Components
@Controller
@Area("promos")
@AvailableComponentClasses({TextComponent.class,
                           ShoppingCartComponent.class})
public static class PromosArea {
   @RequestMapping("/main/promos")
   public String render() {
       return "areas/promos";
   }
}
53
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
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
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.
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
<form>
<input type=”hidden” name=”_pecid”
value=”ff6cefa6-d958-47b1-af70-c82a414f17e1” />
<input type=”text” name=”email” />
...
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 International Limited.}

More Related Content

What's hot

Spring 3.x - Spring MVC
Spring 3.x - Spring MVCSpring 3.x - Spring MVC
Spring 3.x - Spring MVC
Guy Nir
 
Spring MVC Basics
Spring MVC BasicsSpring MVC Basics
Spring MVC Basics
Bozhidar Bozhanov
 
Multi Client Development with Spring
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with Spring
Joshua Long
 
Modern android development
Modern android developmentModern android development
Modern android development
Khiem-Kim Ho Xuan
 
Multi client Development with Spring
Multi client Development with SpringMulti client Development with Spring
Multi client Development with Spring
Joshua Long
 
Spring MVC Annotations
Spring MVC AnnotationsSpring MVC Annotations
Spring MVC Annotations
Jordan Silva
 
Java Web Programming on Google Cloud Platform [2/3] : Datastore
Java Web Programming on Google Cloud Platform [2/3] : DatastoreJava Web Programming on Google Cloud Platform [2/3] : Datastore
Java Web Programming on Google Cloud Platform [2/3] : Datastore
IMC Institute
 
Java Web Programming [3/9] : Servlet Advanced
Java Web Programming [3/9] : Servlet AdvancedJava Web Programming [3/9] : Servlet Advanced
Java Web Programming [3/9] : Servlet Advanced
IMC Institute
 
Java Web Programming on Google Cloud Platform [1/3] : Google App Engine
Java Web Programming on Google Cloud Platform [1/3] : Google App EngineJava Web Programming on Google Cloud Platform [1/3] : Google App Engine
Java Web Programming on Google Cloud Platform [1/3] : Google App Engine
IMC Institute
 
Java Web Programming on Google Cloud Platform [3/3] : Google Web Toolkit
Java Web Programming on Google Cloud Platform [3/3] : Google Web ToolkitJava Web Programming on Google Cloud Platform [3/3] : Google Web Toolkit
Java Web Programming on Google Cloud Platform [3/3] : Google Web Toolkit
IMC Institute
 
Jsf intro
Jsf introJsf intro
Jsf intro
vantinhkhuc
 
Building Highly Reusable Taskflows
Building Highly Reusable TaskflowsBuilding Highly Reusable Taskflows
Building Highly Reusable Taskflows
Steven Davelaar
 
Rest with Java EE 6 , Security , Backbone.js
Rest with Java EE 6 , Security , Backbone.jsRest with Java EE 6 , Security , Backbone.js
Rest with Java EE 6 , Security , Backbone.js
Carol McDonald
 
Create an application with ember
Create an application with ember Create an application with ember
Create an application with ember
Chandra Sekar
 
Key Insights into Development Design Patterns for Magento 2 - Magento Live UK
Key Insights into Development Design Patterns for Magento 2 - Magento Live UKKey Insights into Development Design Patterns for Magento 2 - Magento Live UK
Key Insights into Development Design Patterns for Magento 2 - Magento Live UK
Max Pronko
 
Java Web Programming [6/9] : MVC
Java Web Programming [6/9] : MVCJava Web Programming [6/9] : MVC
Java Web Programming [6/9] : MVC
IMC Institute
 
Spring MVC 3.0 Framework (sesson_2)
Spring MVC 3.0 Framework (sesson_2)Spring MVC 3.0 Framework (sesson_2)
Spring MVC 3.0 Framework (sesson_2)
Ravi Kant Soni (ravikantsoni03@gmail.com)
 
Java Web Programming [8/9] : JSF and AJAX
Java Web Programming [8/9] : JSF and AJAXJava Web Programming [8/9] : JSF and AJAX
Java Web Programming [8/9] : JSF and AJAX
IMC Institute
 
Spring mvc 2.0
Spring mvc 2.0Spring mvc 2.0
Spring mvc 2.0
Rudra Garnaik, PMI-ACP®
 
A Complete Tour of JSF 2
A Complete Tour of JSF 2A Complete Tour of JSF 2
A Complete Tour of JSF 2
Jim Driscoll
 

What's hot (20)

Spring 3.x - Spring MVC
Spring 3.x - Spring MVCSpring 3.x - Spring MVC
Spring 3.x - Spring MVC
 
Spring MVC Basics
Spring MVC BasicsSpring MVC Basics
Spring MVC Basics
 
Multi Client Development with Spring
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with Spring
 
Modern android development
Modern android developmentModern android development
Modern android development
 
Multi client Development with Spring
Multi client Development with SpringMulti client Development with Spring
Multi client Development with Spring
 
Spring MVC Annotations
Spring MVC AnnotationsSpring MVC Annotations
Spring MVC Annotations
 
Java Web Programming on Google Cloud Platform [2/3] : Datastore
Java Web Programming on Google Cloud Platform [2/3] : DatastoreJava Web Programming on Google Cloud Platform [2/3] : Datastore
Java Web Programming on Google Cloud Platform [2/3] : Datastore
 
Java Web Programming [3/9] : Servlet Advanced
Java Web Programming [3/9] : Servlet AdvancedJava Web Programming [3/9] : Servlet Advanced
Java Web Programming [3/9] : Servlet Advanced
 
Java Web Programming on Google Cloud Platform [1/3] : Google App Engine
Java Web Programming on Google Cloud Platform [1/3] : Google App EngineJava Web Programming on Google Cloud Platform [1/3] : Google App Engine
Java Web Programming on Google Cloud Platform [1/3] : Google App Engine
 
Java Web Programming on Google Cloud Platform [3/3] : Google Web Toolkit
Java Web Programming on Google Cloud Platform [3/3] : Google Web ToolkitJava Web Programming on Google Cloud Platform [3/3] : Google Web Toolkit
Java Web Programming on Google Cloud Platform [3/3] : Google Web Toolkit
 
Jsf intro
Jsf introJsf intro
Jsf intro
 
Building Highly Reusable Taskflows
Building Highly Reusable TaskflowsBuilding Highly Reusable Taskflows
Building Highly Reusable Taskflows
 
Rest with Java EE 6 , Security , Backbone.js
Rest with Java EE 6 , Security , Backbone.jsRest with Java EE 6 , Security , Backbone.js
Rest with Java EE 6 , Security , Backbone.js
 
Create an application with ember
Create an application with ember Create an application with ember
Create an application with ember
 
Key Insights into Development Design Patterns for Magento 2 - Magento Live UK
Key Insights into Development Design Patterns for Magento 2 - Magento Live UKKey Insights into Development Design Patterns for Magento 2 - Magento Live UK
Key Insights into Development Design Patterns for Magento 2 - Magento Live UK
 
Java Web Programming [6/9] : MVC
Java Web Programming [6/9] : MVCJava Web Programming [6/9] : MVC
Java Web Programming [6/9] : MVC
 
Spring MVC 3.0 Framework (sesson_2)
Spring MVC 3.0 Framework (sesson_2)Spring MVC 3.0 Framework (sesson_2)
Spring MVC 3.0 Framework (sesson_2)
 
Java Web Programming [8/9] : JSF and AJAX
Java Web Programming [8/9] : JSF and AJAXJava Web Programming [8/9] : JSF and AJAX
Java Web Programming [8/9] : JSF and AJAX
 
Spring mvc 2.0
Spring mvc 2.0Spring mvc 2.0
Spring mvc 2.0
 
A Complete Tour of JSF 2
A Complete Tour of JSF 2A Complete Tour of JSF 2
A Complete Tour of JSF 2
 

Similar to Getting Healthy with Magnolia, Blossom and Spring

Rp 6 session 2 naresh bhatia
Rp 6  session 2 naresh bhatiaRp 6  session 2 naresh bhatia
Rp 6 session 2 naresh bhatia
sapientindia
 
Sviluppare applicazioni cross-platform con Xamarin Forms e il framework Prism...
Sviluppare applicazioni cross-platform con Xamarin Forms e il framework Prism...Sviluppare applicazioni cross-platform con Xamarin Forms e il framework Prism...
Sviluppare applicazioni cross-platform con Xamarin Forms e il framework Prism...
Codemotion
 
Drupal 7 Theming - Behind the scenes
Drupal 7 Theming - Behind the scenes Drupal 7 Theming - Behind the scenes
Drupal 7 Theming - Behind the scenes
ramakesavan
 
Multilingualism makes better programmers
Multilingualism makes better programmersMultilingualism makes better programmers
Multilingualism makes better programmers
Alexander Varwijk
 
Backbone js-slides
Backbone js-slidesBackbone js-slides
Backbone js-slides
DrupalCamp Kyiv Рысь
 
Viking academy backbone.js
Viking academy  backbone.jsViking academy  backbone.js
Viking academy backbone.js
Bert Wijnants
 
Using Backbone.js with Drupal 7 and 8
Using Backbone.js with Drupal 7 and 8Using Backbone.js with Drupal 7 and 8
Using Backbone.js with Drupal 7 and 8
Ovadiah Myrgorod
 
Javascript frameworks: Backbone.js
Javascript frameworks: Backbone.jsJavascript frameworks: Backbone.js
Javascript frameworks: Backbone.js
Soós Gábor
 
.NET Fest 2017. Matteo Pagani. Prism and Xamarin Forms: create cross-platform...
.NET Fest 2017. Matteo Pagani. Prism and Xamarin Forms: create cross-platform....NET Fest 2017. Matteo Pagani. Prism and Xamarin Forms: create cross-platform...
.NET Fest 2017. Matteo Pagani. Prism and Xamarin Forms: create cross-platform...
NETFest
 
New Features of JSR 317 (JPA 2.0)
New Features of JSR 317 (JPA 2.0)New Features of JSR 317 (JPA 2.0)
New Features of JSR 317 (JPA 2.0)
Markus Eisele
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
Richard Leland
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
Richard Leland
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
Richard Leland
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
Richard Leland
 
Managing your camels in the cloud with CI/CD
Managing your camels in the cloud with CI/CDManaging your camels in the cloud with CI/CD
Managing your camels in the cloud with CI/CD
Christian Posta
 
Zotonic tutorial EUC 2013
Zotonic tutorial EUC 2013Zotonic tutorial EUC 2013
Zotonic tutorial EUC 2013
Arjan
 
Red Hat Agile integration Workshop Labs
Red Hat Agile integration Workshop LabsRed Hat Agile integration Workshop Labs
Red Hat Agile integration Workshop Labs
Judy Breedlove
 
Web Components v1
Web Components v1Web Components v1
Web Components v1
Mike Wilcox
 
The Ring programming language version 1.9 book - Part 54 of 210
The Ring programming language version 1.9 book - Part 54 of 210The Ring programming language version 1.9 book - Part 54 of 210
The Ring programming language version 1.9 book - Part 54 of 210
Mahmoud Samir Fayed
 
Meteor + Ionic Introduction
Meteor + Ionic IntroductionMeteor + Ionic Introduction
Meteor + Ionic Introduction
LearningTech
 

Similar to Getting Healthy with Magnolia, Blossom and Spring (20)

Rp 6 session 2 naresh bhatia
Rp 6  session 2 naresh bhatiaRp 6  session 2 naresh bhatia
Rp 6 session 2 naresh bhatia
 
Sviluppare applicazioni cross-platform con Xamarin Forms e il framework Prism...
Sviluppare applicazioni cross-platform con Xamarin Forms e il framework Prism...Sviluppare applicazioni cross-platform con Xamarin Forms e il framework Prism...
Sviluppare applicazioni cross-platform con Xamarin Forms e il framework Prism...
 
Drupal 7 Theming - Behind the scenes
Drupal 7 Theming - Behind the scenes Drupal 7 Theming - Behind the scenes
Drupal 7 Theming - Behind the scenes
 
Multilingualism makes better programmers
Multilingualism makes better programmersMultilingualism makes better programmers
Multilingualism makes better programmers
 
Backbone js-slides
Backbone js-slidesBackbone js-slides
Backbone js-slides
 
Viking academy backbone.js
Viking academy  backbone.jsViking academy  backbone.js
Viking academy backbone.js
 
Using Backbone.js with Drupal 7 and 8
Using Backbone.js with Drupal 7 and 8Using Backbone.js with Drupal 7 and 8
Using Backbone.js with Drupal 7 and 8
 
Javascript frameworks: Backbone.js
Javascript frameworks: Backbone.jsJavascript frameworks: Backbone.js
Javascript frameworks: Backbone.js
 
.NET Fest 2017. Matteo Pagani. Prism and Xamarin Forms: create cross-platform...
.NET Fest 2017. Matteo Pagani. Prism and Xamarin Forms: create cross-platform....NET Fest 2017. Matteo Pagani. Prism and Xamarin Forms: create cross-platform...
.NET Fest 2017. Matteo Pagani. Prism and Xamarin Forms: create cross-platform...
 
New Features of JSR 317 (JPA 2.0)
New Features of JSR 317 (JPA 2.0)New Features of JSR 317 (JPA 2.0)
New Features of JSR 317 (JPA 2.0)
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
Managing your camels in the cloud with CI/CD
Managing your camels in the cloud with CI/CDManaging your camels in the cloud with CI/CD
Managing your camels in the cloud with CI/CD
 
Zotonic tutorial EUC 2013
Zotonic tutorial EUC 2013Zotonic tutorial EUC 2013
Zotonic tutorial EUC 2013
 
Red Hat Agile integration Workshop Labs
Red Hat Agile integration Workshop LabsRed Hat Agile integration Workshop Labs
Red Hat Agile integration Workshop Labs
 
Web Components v1
Web Components v1Web Components v1
Web Components v1
 
The Ring programming language version 1.9 book - Part 54 of 210
The Ring programming language version 1.9 book - Part 54 of 210The Ring programming language version 1.9 book - Part 54 of 210
The Ring programming language version 1.9 book - Part 54 of 210
 
Meteor + Ionic Introduction
Meteor + Ionic IntroductionMeteor + Ionic Introduction
Meteor + Ionic Introduction
 

More from Magnolia

The SEO Workflow
The SEO WorkflowThe SEO Workflow
The SEO Workflow
Magnolia
 
Magnolia 6 release walkthrough
Magnolia 6 release walkthroughMagnolia 6 release walkthrough
Magnolia 6 release walkthrough
Magnolia
 
Buzzword bingo: The real deal behind omnichannel, personalization and headless
Buzzword bingo: The real deal behind  omnichannel, personalization and headlessBuzzword bingo: The real deal behind  omnichannel, personalization and headless
Buzzword bingo: The real deal behind omnichannel, personalization and headless
Magnolia
 
Developing Magnolia based sites correctly, quickly and efficiently
Developing Magnolia based sites correctly, quickly and efficientlyDeveloping Magnolia based sites correctly, quickly and efficiently
Developing Magnolia based sites correctly, quickly and efficiently
Magnolia
 
Integrating e-Commerce into your Customer Experience
Integrating e-Commerce into your Customer ExperienceIntegrating e-Commerce into your Customer Experience
Integrating e-Commerce into your Customer Experience
Magnolia
 
Customer Engagement in the Digital Era
Customer Engagement in the Digital EraCustomer Engagement in the Digital Era
Customer Engagement in the Digital Era
Magnolia
 
The Age of the IOT & Digital Business
The Age of the IOT & Digital BusinessThe Age of the IOT & Digital Business
The Age of the IOT & Digital Business
Magnolia
 
Using Magnolia in a Microservices Architecture
Using Magnolia in a Microservices ArchitectureUsing Magnolia in a Microservices Architecture
Using Magnolia in a Microservices Architecture
Magnolia
 
A modern front end development workflow for Magnolia at Atlassian
A modern front end development workflow for Magnolia at AtlassianA modern front end development workflow for Magnolia at Atlassian
A modern front end development workflow for Magnolia at Atlassian
Magnolia
 
Magnolia Conference 2015 - Pascal Mangold's keynote
Magnolia Conference 2015 - Pascal Mangold's keynoteMagnolia Conference 2015 - Pascal Mangold's keynote
Magnolia Conference 2015 - Pascal Mangold's keynote
Magnolia
 
Product keynote - introducing Magnolia 5.4
Product keynote - introducing Magnolia 5.4Product keynote - introducing Magnolia 5.4
Product keynote - introducing Magnolia 5.4
Magnolia
 
Launching Magnolia on demand
Launching Magnolia on demandLaunching Magnolia on demand
Launching Magnolia on demand
Magnolia
 
Front-end developers - build Magnolia sites faster
Front-end developers - build Magnolia sites fasterFront-end developers - build Magnolia sites faster
Front-end developers - build Magnolia sites faster
Magnolia
 
Magnolia and beacons: how do they work best together?
Magnolia and beacons: how do they work best together?Magnolia and beacons: how do they work best together?
Magnolia and beacons: how do they work best together?
Magnolia
 
Magnolia and the IOT
Magnolia and the IOTMagnolia and the IOT
Magnolia and the IOT
Magnolia
 
Internationalization for globalized enterprise websites
Internationalization for globalized enterprise websitesInternationalization for globalized enterprise websites
Internationalization for globalized enterprise websites
Magnolia
 
The new visana website how to fit a square peg into a round hole
The new visana website   how to fit a square peg into a round holeThe new visana website   how to fit a square peg into a round hole
The new visana website how to fit a square peg into a round hole
Magnolia
 
Solving for complex UI designs: a front-end perspective and approach
Solving for complex UI designs: a front-end perspective and approachSolving for complex UI designs: a front-end perspective and approach
Solving for complex UI designs: a front-end perspective and approach
Magnolia
 
Extending Magnolia with our solutions
Extending Magnolia with our solutionsExtending Magnolia with our solutions
Extending Magnolia with our solutions
Magnolia
 
Boost your online e commerce with magnolia
Boost your online e commerce with magnoliaBoost your online e commerce with magnolia
Boost your online e commerce with magnolia
Magnolia
 

More from Magnolia (20)

The SEO Workflow
The SEO WorkflowThe SEO Workflow
The SEO Workflow
 
Magnolia 6 release walkthrough
Magnolia 6 release walkthroughMagnolia 6 release walkthrough
Magnolia 6 release walkthrough
 
Buzzword bingo: The real deal behind omnichannel, personalization and headless
Buzzword bingo: The real deal behind  omnichannel, personalization and headlessBuzzword bingo: The real deal behind  omnichannel, personalization and headless
Buzzword bingo: The real deal behind omnichannel, personalization and headless
 
Developing Magnolia based sites correctly, quickly and efficiently
Developing Magnolia based sites correctly, quickly and efficientlyDeveloping Magnolia based sites correctly, quickly and efficiently
Developing Magnolia based sites correctly, quickly and efficiently
 
Integrating e-Commerce into your Customer Experience
Integrating e-Commerce into your Customer ExperienceIntegrating e-Commerce into your Customer Experience
Integrating e-Commerce into your Customer Experience
 
Customer Engagement in the Digital Era
Customer Engagement in the Digital EraCustomer Engagement in the Digital Era
Customer Engagement in the Digital Era
 
The Age of the IOT & Digital Business
The Age of the IOT & Digital BusinessThe Age of the IOT & Digital Business
The Age of the IOT & Digital Business
 
Using Magnolia in a Microservices Architecture
Using Magnolia in a Microservices ArchitectureUsing Magnolia in a Microservices Architecture
Using Magnolia in a Microservices Architecture
 
A modern front end development workflow for Magnolia at Atlassian
A modern front end development workflow for Magnolia at AtlassianA modern front end development workflow for Magnolia at Atlassian
A modern front end development workflow for Magnolia at Atlassian
 
Magnolia Conference 2015 - Pascal Mangold's keynote
Magnolia Conference 2015 - Pascal Mangold's keynoteMagnolia Conference 2015 - Pascal Mangold's keynote
Magnolia Conference 2015 - Pascal Mangold's keynote
 
Product keynote - introducing Magnolia 5.4
Product keynote - introducing Magnolia 5.4Product keynote - introducing Magnolia 5.4
Product keynote - introducing Magnolia 5.4
 
Launching Magnolia on demand
Launching Magnolia on demandLaunching Magnolia on demand
Launching Magnolia on demand
 
Front-end developers - build Magnolia sites faster
Front-end developers - build Magnolia sites fasterFront-end developers - build Magnolia sites faster
Front-end developers - build Magnolia sites faster
 
Magnolia and beacons: how do they work best together?
Magnolia and beacons: how do they work best together?Magnolia and beacons: how do they work best together?
Magnolia and beacons: how do they work best together?
 
Magnolia and the IOT
Magnolia and the IOTMagnolia and the IOT
Magnolia and the IOT
 
Internationalization for globalized enterprise websites
Internationalization for globalized enterprise websitesInternationalization for globalized enterprise websites
Internationalization for globalized enterprise websites
 
The new visana website how to fit a square peg into a round hole
The new visana website   how to fit a square peg into a round holeThe new visana website   how to fit a square peg into a round hole
The new visana website how to fit a square peg into a round hole
 
Solving for complex UI designs: a front-end perspective and approach
Solving for complex UI designs: a front-end perspective and approachSolving for complex UI designs: a front-end perspective and approach
Solving for complex UI designs: a front-end perspective and approach
 
Extending Magnolia with our solutions
Extending Magnolia with our solutionsExtending Magnolia with our solutions
Extending Magnolia with our solutions
 
Boost your online e commerce with magnolia
Boost your online e commerce with magnoliaBoost your online e commerce with magnolia
Boost your online e commerce with magnolia
 

Recently uploaded

GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
Neo4j
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...
Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...
Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...
Zilliz
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
Neo4j
 
Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...
Zilliz
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
Aftab Hussain
 
20 Comprehensive Checklist of Designing and Developing a Website
20 Comprehensive Checklist of Designing and Developing a Website20 Comprehensive Checklist of Designing and Developing a Website
20 Comprehensive Checklist of Designing and Developing a Website
Pixlogix Infotech
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
James Anderson
 
Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
Rohit Gautam
 
“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”
Claudio Di Ciccio
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
Zilliz
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
Data structures and Algorithms in Python.pdf
Data structures and Algorithms in Python.pdfData structures and Algorithms in Python.pdf
Data structures and Algorithms in Python.pdf
TIPNGVN2
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
Daiki Mogmet Ito
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
danishmna97
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 

Recently uploaded (20)

GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...
Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...
Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
 
Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
 
20 Comprehensive Checklist of Designing and Developing a Website
20 Comprehensive Checklist of Designing and Developing a Website20 Comprehensive Checklist of Designing and Developing a Website
20 Comprehensive Checklist of Designing and Developing a Website
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
 
Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
 
“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
Data structures and Algorithms in Python.pdf
Data structures and Algorithms in Python.pdfData structures and Algorithms in Python.pdf
Data structures and Algorithms in Python.pdf
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 

Getting Healthy with Magnolia, Blossom and Spring

  • 1. !1 Blossom in the Real World
  • 2. Sr. Software Engineer, Magnolia Lead developer of Blossom Module Spring Framework user since 2005 Tobias Mattsson 2@sigget
  • 3. 3 Jan Haderka Head of Support, Magnolia @rah003
  • 4. 4 Casey Dement VP of Architecture, Sharecare @casey_dement
  • 6. Magnolia + Spring = Blossom 6
  • 9. TEMPLATEREQUEST CONTENT CMS + Blossom 9 CONTROLLER MODEL VIEW
  • 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
  • 12. PAGES CONTAIN 0:n AREAS 12 PAGE AREA A R E A AREA
  • 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. 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. 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
  • 18. Blossom 3.0 18 Update for Magnolia 5 series Requires Magnolia 5.1 new ways of building dialogs availability annotation
  • 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. 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. 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. 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. 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
  • 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
  • 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. Now The Real World 29
  • 32. 32
  • 33. How do I get started on my project? 33
  • 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. How would I build a REST interface to my CMS content using Blossom? 35
  • 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. REST Controller @Controller public class ProductsRestController { ! @RequestMapping("/products/{productId}") public Product findProduct(@PathVariable String productId) { // implementation omitted } } 37
  • 38. Can I leverage Magnolia's caching functionality to improve the performance of my Spring app? 38
  • 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. How can I present dialogs in different languages using Blossom? 40
  • 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. ! ! /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. How do I migrate my existing site to Magnolia/ Blossom? 43
  • 44. How can I integrate Spring Security? 44
  • 45. 45
  • 46. How can I dependency inject spring beans into RenderingModels? 46
  • 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. 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
  • 50. Rendering an Area FreeMarker [@cms.area name="main" /] ! JSP <cms:area name="main" /> 50
  • 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. 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. 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. 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. 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. 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. 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. 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” /> ...
  • 60. Spring Web Flow 60 REQUEST LANDING PAGE SPRING WEB FLOW
  • 61. Spring Web Flow 61 REQUEST LANDING PAGE FORM SUBMIT? SPRING WEB FLOW
  • 62. 62 Trademarks Other trademarks are the property of their respective owners. Magnolia The Pulse are trademarks of Magnolia International Limited.}