54
APACHE SLING & FRIENDS TECH MEETUP BERLIN, 22-24 SEPTEMBER 2014 Lazy AEM developer Feike Visser, Adobe, @heervisscher

Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

  • Upload
    others

  • View
    13

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

APACHE SLING & FRIENDS TECH MEETUP BERLIN, 22-24 SEPTEMBER 2014

Lazy AEM developer Feike Visser, Adobe, @heervisscher

Page 2: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

adaptTo() 2014 2

Sling Models & Sightly in Action

Page 3: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

adaptTo() 2014 3

Introduction to Sling Models / Sightly

Page 4: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

What is Sling Models

adaptTo() 2014 4

Creating an adaptable class from a POJO by annotations

Resource r = getResource();

return r.adaptTo(YourCustom.class);

@Model(adaptables = Resource.class)

public class YourCustom {

...

}

Page 5: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

What is Sling Models

adaptTo() 2014 5

The ‘old-days’….

@Component

@Service

@Properties({

@Property(name = "adaptables", value = {"Resource" }),

@Property(name = "adapters", value = {"YourCustom" })

})

public class MyAdapterFactory implements AdapterFactory{

public <AdapterType> AdapterType

getAdapter(final Object adaptable, Class<AdapterType> type){

return new MyClassAdapter(adaptable);

}

}

Page 6: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

What is Sling Models

adaptTo() 2014 6

Injecting

@Model(adaptables = Resource.class)

public class YourCustom {

@Inject // we expected always an email-property

private String email;

@Inject @Optional // firstname can be empty

private String firstName;

// read property ‘surname‘ if empty, use ‘empty‘

@Inject @Named(“surname“) @Default(values=“empty“)

private String lastName;

}

Page 7: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

What is Sling Models

adaptTo() 2014 7

@Model(adaptables = Resource.class)

public class YourCustom {

@Inject // OSGi Service

private Externalizer externalizer;

@PostConstruct

protected void init() {

// gets executed after the class is created

// set to protected, so it can be unit-tested

}

}

Page 8: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

What is Sling Models

adaptTo() 2014 8

@Model(adaptables = Resource.class)

public class YourCustom {

@Self //(available in 1.1.10)

private Resource resource;

public YourCustom(Resource resource) {

// to get access to the adaptor

this.resource = resource;

}

}

Page 9: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Sling Models

adaptTo() 2014 9

Before After

Page 11: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

What is Sightly

adaptTo() 2014 11

Use HTML5-attributes to implement basic logic

<div data-sly-test=“${wcmmode.edit}“>

Show this in edit mode...

</div>

Page 12: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

What is Sightly

adaptTo() 2014 12

Standard bindings are available

<h2>${currentPage.title}</h2>

<h3>${pageProperties.jcr:title || ‘No title‘}</h3>

<h4>${properties[‘address/officeName‘]}</h4>

<ul data-sly-list=“${currentPage.listChildren}“>

<li>Page title: ${item.title}</li>

</ul>

Page 13: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

What is Sightly

adaptTo() 2014 13

Basic comparisons are available

<h2>${currentPage.title}</h2>

<div data-sly-test=“${ (currentPage.title == ‘test‘) }“>

// show the parsys when the title is test

<div data-sly-resource=“${ ‘par‘

@ resourceType=‘foundation/components/parsys‘“>

</div>

</div>

Page 14: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

What is Sightly

adaptTo() 2014 14

What about non-basic logic?

<div data-sly-use.sample=“com.yourproject.YourComponent“>

// display the value from the Java-class

${ sample.myCustomValue }

</div>

1. Class extends WCMUse-class

2. Class implements Use-interface

3. Class is adaptable from Resource

4. Class is adaptable from Request

Page 15: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

What is Sightly

adaptTo() 2014 15

JSP Sightly

Page 17: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

adaptTo() 2014 17

How Sling Models and Sightly meet?

Page 18: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

How Sightly and Sling Models meet?

adaptTo() 2014 18

data-sly-use does the trick with a class adaptable from Resource or Request

<div data-sly-use.myClass=”mysite.myproject.HeaderComponent”>

${ myClass.fullName }

</div>

Page 19: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

How Sightly and Sling Models meet?

adaptTo() 2014 19

@Model(adaptables = Resource.class)

public class HeaderComponent {

@Inject @Default(values=“Feike“)

public String firstName; // maps to property firstName

public String fullName;

@PostConstruct

protected void init() {

fullname += firstName + “ Visser“;

}

Page 20: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

How Sightly and Sling Models meet?

adaptTo() 2014 20

Can we pass in parameters?

<div data-sly-use.myClass=”${ ‘mysite.myproject.HeaderComponent‘ @

param1=currentPage, param2=‘advanced‘ }”>

${ myClass.fullName }

</div>

Only works if class is adaptable from Request

Page 21: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

How Sightly and Sling Models meet?

adaptTo() 2014 21

@Model(adaptables = SlingHttpServletRequest.class)

public class HeaderComponent {

@Inject

public Page param1; // maps to param1 parameter

@Inject

public String param2; // maps to param2 parameter

}

Page 22: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

How Sightly and Sling Models meet?

adaptTo() 2014 22

Can we re-use the bindings?

${ currentPage.title }

${ pageProperties.jcr:title }

@Model(adaptables = SlingHttpServletRequest.class)

public class HeaderComponent {

@Inject

public Page currentPage; // maps to currentPage binding

}

Page 23: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

How Sightly and Sling Models meet?

adaptTo() 2014 23

Common sense still applies, only write code if needed

<div data-sly-use.person=“project.Person“>

${person.firstName}

</div>

<div>

${properties.firstName}

</div>

Page 24: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

adaptTo() 2014 24

Example: Lat-Long component

Page 25: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Lat-long component

adaptTo() 2014 25

User enters address, lat+long is displayed

<div class="address" data-sly-use.geocode="components.LatLongComponent">

<div class="latlong">

Lat : ${geocode.coordinates.lat},

Long : ${geocode.coordinates.lng}

</div>

</div>

Page 26: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Lat-long component

adaptTo() 2014 26

@Model(adaptables=Resource.class)

public class LatLongComponent {

@Inject @Named("address") @Default(values=DEFAULT)

protected String addressDescription;

@Inject // Injecting Service here

private GeocodeProvider geocode;

@PostConstruct

protected void init() throws AddressException {

coordinates = geocode.geocode(addressDescription);

}

}

Page 27: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Lat-long component

adaptTo() 2014 27

Sightly supports different ways to access props

<div class="address" data-sly-use.geocode="components.LatLongComponent">

<div class="latlong">

Lat : ${geocode.coordinates.lat},

Long : ${geocode.coordinates.getLng}

</div>

<div class="addressDescrption"

data-sly-text="${properties.address || geocode.DEFAULT}">

</div>

</div>

Page 28: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

adaptTo() 2014 28

Example: Absolute URL

Page 29: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Absolute URL

adaptTo() 2014 29

Render the absolute url of the current-page

<meta

data-sly-use.externalizer="components.ExternalUrl"

property="og:url"

content="${externalizer.absoluteUrl @ context='uri'}.html" />

Page 30: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Absolute URL

adaptTo() 2014 30

@Model(adaptables = SlingHttpServletRequest.class)

public class ExternalUrl {

@Inject

private Externalizer externalizer;

@Inject // To get the currentPage

private PageManagerFactory pageMan;

private SlingHttpServletRequest request;

public ExternalUrl(SlingHttpServletRequest request) {

// needed for the Externalizer

this.request = request;

}

}

Page 31: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Absolute URL

adaptTo() 2014 31

@Model(adaptables = SlingHttpServletRequest.class)

public class ExternalUrl {

@PostConstruct

protected void init() {

String path = getCurrentPage().getPath();

absoluteUrl = externalizer.absoluteLink(request, "http", path);

}

private Page getCurrentPage() {

PageManager pm = pageMan.getPageManager(request.getResourceResolver());

return pm.getContainingPage(request.getResource());

}

}

Page 32: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

This is not lazy enough

adaptTo() 2014 32

Have to code the getCurrentPage() Fixed to currentPage Not reusable enough

Page 33: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Absolute URL

adaptTo() 2014 33

@Model(adaptables = SlingHttpServletRequest.class)

public class ExternalUrl {

@Inject

private Externalizer externalizer;

@Inject // Using the bindings from Sightly (${currentPage.path}

protected Page currentPage;

@Inject @Optional // parameter from data-sly-use

protected String path;

}

Page 34: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Absolute URL

adaptTo() 2014 34

@Model(adaptables = SlingHttpServletRequest.class)

public class ExternalUrl {

@PostConstruct

protected void init() {

String relPath = currentPage.getPath();

if ( path != null) { // check if there is a parameter

relPath = path;

}

absoluteUrl = externalize(relPath);

}

protected String externalize(String path) {

return externalizer.absoluteLink(request, "http", path);

}

}

Page 35: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Absolute URL

adaptTo() 2014 35

Parameters can be specified after the @

<meta

data-sly-use.externalizer="${'components.ExternalUrl'

@ path=resourcePage.path}"

property="og:url"

content="${externalizer.absoluteUrl @ context='uri'}.html" />

Page 36: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Absolute URL (unit-testing?)

adaptTo() 2014 36

@Spy

private ExternalUrl externalUrl = new ExternalUrl(null);

@Before

public void setup() {

String path = "/content/adaptTo/example";

String extPath = "http://localhost:4502/adaptTo";

doReturn(extPath).when(externalUrl).externalize(path);

}

@Test

public void testWhenNoPathParameterIsSpecified() {

externalUrl.init();

Assert.assertNotNull(externalUrl.absoluteUrl);

}

Page 37: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

adaptTo() 2014 37

Bindings, Bindings, Bindings

Page 38: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Bindings example

adaptTo() 2014 38

Page-oriented functionality Reuse the Sightly bindings Expose this via a custom bindings Use the binding in your Sling model class

Page 39: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Bindings

adaptTo() 2014 39

Custom Page-class

@Model(adaptables=Page.class)

public class MyCustomPage {

private Page page;

public String getTitle() {

return "MyProject : " + page.getTitle();

}

}

Page 40: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Bindings

adaptTo() 2014 40

Re-use Sightly binding, adding new binding

public class CustomBindingProvider implements BindingsValuesProvider {

@Override

public void addBindings(Bindings bindings) {

if ( bindings.containsKey(WCMBindings.CURRENT_PAGE)) {

Page current = (Page) bindings.get(WCMBindings.CURRENT_PAGE);

bindings.put("customPage", current.adaptTo(MyCustomPage.class));

}

}

Page 41: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Bindings

adaptTo() 2014 41

Make sure your BVP is *after* the Sightly-BVP

@Service

@Component(immediate = true)

@Properties({

@Property(name = "javax.script.name", value = "sightly"),

@Property(name = "service.ranking", intValue = 100)

})

public class CustomBindingProvider implements BindingsValuesProvider {

...

}

Page 42: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Bindings

adaptTo() 2014 42

New binding available in your components

<div>

<h1>${customPage.title}</h1>

</div>

Page 43: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

Bindings

adaptTo() 2014 43

And Injectable in your Sling Model class

@Model(adaptables=SlingHttpServletRequest.class)

public class ContentComponent {

@Inject

private MyCustomPage customPage;

}

Page 44: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

adaptTo() 2014 44

data-sly-template example

Page 45: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

data-sly-template example

adaptTo() 2014 45

Multiple page layouts Can be chosen by the author Shows the power for data-sly-template

Page 46: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

data-sly-template

adaptTo() 2014 46

Can take parameters, can be in a separate file

<template data-sly-template.page="${ withParsys }">

<div class="content">

<div

data-sly-test="${ withParsys != 'false' }"

data-sly-resource="${'par' @

resourceType='foundation/components/parsys'}">

</div>

</div>

</template>

Page 47: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

data-sly-template

adaptTo() 2014 47

data-sly-call invokes the template

<div

data-sly-test.layoutFile="${ properties.layout || ‘layout1.html'}"

data-sly-use.layout="${layoutFile}"

data-sly-call="${layout.page @ withParsys = 'true'}">

</div>

Page 48: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

adaptTo() 2014 48

(bonus) Sightly questions from the field

Page 49: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

If-then-else?

adaptTo() 2014 49

Can we do an if-then-else?

<div data-sly-test.authorMode=“${wcmmode.edit || wcmmode.preview}“></div>

<div data-sly-test=“${!authorMode}“></div>

Page 50: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

String-concat?

adaptTo() 2014 50

String concatenation can be done via @ format

<div

data-sly-test.concat="${ 'This is page {0}, with title {1}' @

format=[currentPage.name,currentPage.title]}">

${concat}

</div>

Page 51: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

data-sly-unwrap, friend or enemy?

adaptTo() 2014 51

data-sly-unwrap *can* be used for declaration

<sightly data-sly-use.section="components.YourComponent" data-sly-unwrap/>

<sightly

data-sly-test.localVar=“${wcmmode.edit || wcmmode.preview}“

data-sly-unwrap/>

Page 52: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

variables

adaptTo() 2014 52

Can I increment a counter? No…, via data-sly-use

data-sly-list offers quite a range a helper values

<div data-sly-list=“${currentPage.listChildren}“>

${itemList.index}

${itemList.count}

${itemList.first}

${itemList.last}

${itemList.odd}

${itemList.even}

</div>

Page 53: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

formatting

adaptTo() 2014 53

Is there (date)-formatting? No, via data-sly-use

<div data-sly-use.dateFormat=“${‘yourClass‘ @ date=dateValue}“>

${dateFormat.formattedValue}

</div>

Page 54: Lazy AEM developer Feike Visser, Adobe, @heervisscher · Introduction to Sling Models / Sightly . What is Sling Models adaptTo() 2014 4 Creating an adaptable class from a POJO by

adaptTo() 2014 54

Questions?