SlideShare ist ein Scribd-Unternehmen logo
1 von 62
Downloaden Sie, um offline zu lesen
!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.}

Weitere ähnliche Inhalte

Was ist angesagt?

Spring 3.x - Spring MVC
Spring 3.x - Spring MVCSpring 3.x - Spring MVC
Spring 3.x - Spring MVCGuy Nir
 
Multi Client Development with Spring
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with SpringJoshua Long
 
Multi client Development with Spring
Multi client Development with SpringMulti client Development with Spring
Multi client Development with SpringJoshua Long
 
Spring MVC Annotations
Spring MVC AnnotationsSpring MVC Annotations
Spring MVC AnnotationsJordan 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] : DatastoreIMC 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 AdvancedIMC 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 EngineIMC 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 ToolkitIMC Institute
 
Building Highly Reusable Taskflows
Building Highly Reusable TaskflowsBuilding Highly Reusable Taskflows
Building Highly Reusable TaskflowsSteven 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.jsCarol 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 UKMax Pronko
 
Java Web Programming [6/9] : MVC
Java Web Programming [6/9] : MVCJava Web Programming [6/9] : MVC
Java Web Programming [6/9] : MVCIMC Institute
 
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 AJAXIMC Institute
 
A Complete Tour of JSF 2
A Complete Tour of JSF 2A Complete Tour of JSF 2
A Complete Tour of JSF 2Jim Driscoll
 

Was ist angesagt? (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
 

Ähnlich wie 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 bhatiasapientindia
 
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 programmersAlexander Varwijk
 
Viking academy backbone.js
Viking academy  backbone.jsViking academy  backbone.js
Viking academy backbone.jsBert 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 8Ovadiah Myrgorod
 
Javascript frameworks: Backbone.js
Javascript frameworks: Backbone.jsJavascript frameworks: Backbone.js
Javascript frameworks: Backbone.jsSoó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
 
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/CDChristian Posta
 
Zotonic tutorial EUC 2013
Zotonic tutorial EUC 2013Zotonic tutorial EUC 2013
Zotonic tutorial EUC 2013Arjan
 
Red Hat Agile integration Workshop Labs
Red Hat Agile integration Workshop LabsRed Hat Agile integration Workshop Labs
Red Hat Agile integration Workshop LabsJudy Breedlove
 
Web Components v1
Web Components v1Web Components v1
Web Components v1Mike 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 210Mahmoud Samir Fayed
 
Meteor + Ionic Introduction
Meteor + Ionic IntroductionMeteor + Ionic Introduction
Meteor + Ionic IntroductionLearningTech
 

Ähnlich wie 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
 

Mehr von Magnolia

The SEO Workflow
The SEO WorkflowThe SEO Workflow
The SEO WorkflowMagnolia
 
Magnolia 6 release walkthrough
Magnolia 6 release walkthroughMagnolia 6 release walkthrough
Magnolia 6 release walkthroughMagnolia
 
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 headlessMagnolia
 
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 efficientlyMagnolia
 
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 ExperienceMagnolia
 
Customer Engagement in the Digital Era
Customer Engagement in the Digital EraCustomer Engagement in the Digital Era
Customer Engagement in the Digital EraMagnolia
 
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 BusinessMagnolia
 
Using Magnolia in a Microservices Architecture
Using Magnolia in a Microservices ArchitectureUsing Magnolia in a Microservices Architecture
Using Magnolia in a Microservices ArchitectureMagnolia
 
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 AtlassianMagnolia
 
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 keynoteMagnolia
 
Product keynote - introducing Magnolia 5.4
Product keynote - introducing Magnolia 5.4Product keynote - introducing Magnolia 5.4
Product keynote - introducing Magnolia 5.4Magnolia
 
Launching Magnolia on demand
Launching Magnolia on demandLaunching Magnolia on demand
Launching Magnolia on demandMagnolia
 
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 fasterMagnolia
 
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 IOTMagnolia
 
Internationalization for globalized enterprise websites
Internationalization for globalized enterprise websitesInternationalization for globalized enterprise websites
Internationalization for globalized enterprise websitesMagnolia
 
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 holeMagnolia
 
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 approachMagnolia
 
Extending Magnolia with our solutions
Extending Magnolia with our solutionsExtending Magnolia with our solutions
Extending Magnolia with our solutionsMagnolia
 
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 magnoliaMagnolia
 

Mehr von 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
 

Kürzlich hochgeladen

Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdfChristopherTHyatt
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 

Kürzlich hochgeladen (20)

Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 

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