SlideShare uma empresa Scribd logo
1 de 74
Baixar para ler offline
Rich Portlet
                                                                   Development

                                                                                                            Jennifer Bourey
                                               Jasig Spring Conference, March 9, 2010



© Copyright Unicon, Inc., 2006. This work is the intellectual property of Unicon, Inc. Permission is granted for this material to be shared for non-
commercial, educational purposes, provided that this copyright statement appears on the reproduced materials and notice is given that the copying is
by permission of Unicon, Inc. To disseminate otherwise or to republish requires written permission from Unicon, Inc.
Portlet Development Goals

• Make
 – life easier
 – development faster
 – portlets shinier
Create an Accessible 2-Column Layout
Accessible Two-Column Layout
Using the Fluid Skinning System
<div class="fl-col-flex2">

    <!-- start: left panel -->
    <div class="fl-col">

         <h1>I'm the left column!</h1>

    </div><!-- end: left panel -->



    <!-- start: right panel -->
    <div class="fl-col">

         <h1>I'm the right column!</h1>

    </div><!-- end: right panel -->

</div>
Accessible Two-Column Layout




     fl-col                  fl-col


              fl-col-flex2
Fluid Skinning System

• Layout wrappers and containers
• Convenience classnames
  – GUI elements: Tabs, menus, icons, widgets
  – font family, size, and formatting

• Theming
• Accessibility
  – easy page linearization
  – tested for usabiltity effectiveness, specifically
    colorblindness
  – works with Assistive Technology
Allow Users to Page Through a List
Paging Through a List
More from Fluid Infusion

• Components
  – Pager
  – Reorderers (list, grid, and image)
  – Uploader
  – Progressbar
  – Inline text edit

• http://fluidproject.org/releases/1.1.2/demos/
Allow Users to Select a Date
Selecting a Date
jQuery UI Datepicker
<div>
    <label>Start date:</label>
    <input class="cal-datepicker"></input>
</div>

<script type="text/javascript">
    $(document).ready(function(){
        $(".cal-datepicker").datepicker();
    });
</script>
jQuery UI Widgets

• Widgets
  – Accordion
  – Datepicker
  – Dialog
  – Progressbar
  – Slider
  – Tabs

• Demos: http://jqueryui.com/demos/
Use Javascript Effects
jQuery Effects
jQuery UI

• Effects
  – show, hide, toggle, color animation
  – add/remove/toggle/switch css class

• Demos: http://jqueryui.com/demos/
Improve Javascript Performance
Improve UI Performance

• Minify code
• Minimize HTTP requests
• Apply cache headers
• GZip resources
Jasig Resource Server

• Server Webapp
  – Library of popular CSS, JS, and image resources
  – Provide consistent URLs
  – Cache, minify, and gzip hosted resources

• Utilities
  – Filters for caching and gzipping
  – JSP tag for including files from resource server

• Bundled with uPortal 3.1+
Minify code: YUI Maven Plugin
<plugin>
    <groupId>net.sf.alchim</groupId>
    <artifactId>yuicompressor-maven-plugin</artifactId>
    <version>0.7.1</version>
    <executions>
         <execution>
             <goals><goal>compress</goal></goals>
         </execution>
    </executions>
    <configuration>
         <excludes>
             <exclude>**/*.min.js</exclude>
         </excludes>
         <linebreakpos>10000</linebreakpos>
         <suffix>.min</suffix>
         <jswarn>false</jswarn>
    </configuration>
</plugin>
Cache Headers: Resource Server
<filter>
    <filter-name>CacheExpiresFilter</filter-name>
    <filter-class>
         org.jasig.resourceserver.utils.filter.CacheExpirationFilter
    </filter-class>

    <!-- Length of time to set in cache headers (in seconds) -->
    <init-param>
        <param-name>cacheMaxAge</param-name>
        <param-value>31536000</param-value>
    </init-param>

    <!-- Time between regenerating cache header strings (in millis) -->
    <init-param>
        <param-name>regenerateHeadersInterval</param-name>
        <param-value>1000</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>CacheExpiresFilter</filter-name>
    <url-pattern>/rs/*</url-pattern>
</filter-mapping>
GZip CSS and JS
<filter>
    <filter-name>pageCachingFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</
filter-class>
    <init-param>
         <param-name>targetFilterLifecycle</param-name>
         <param-value>true</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>pageCachingFilter</filter-name>
    <url-pattern>*.js</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>pageCachingFilter</filter-name>
    <url-pattern>*.css</url-pattern>
</filter-mapping>
GZip CSS and JS
<bean id="cacheManager"
 class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="cacheManagerName" value="ResourceServer.cacheManager" />
</bean>

<bean id="pageCachingFilter"
 class="org.jasig.resourceserver.utils.cache.ConfigurablePageCachingFilter">
    <constructor-arg ref="cacheManager"/>
    <constructor-arg value="SimplePageCachingFilter"/>
</bean>
GZip HTML: Tomcat

<Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000" redirectPort="8443"
    emptySessionPath="true"
    compression="on"
    compressableMimeType="text/html,text/xml,text/plain" />
Before
After
Interact with Portlet Session and
      Preferences via AJAX
AJAX Servlet


                          Portlet
                         Controller
Browser



                          Servlet
                         Controller



            No portlet preferences access
            No portlet session access
Jasig Ajax Portlet Support



                   Portlet
Browser
                  Controller




                   Servlet
                  Controller
Jasig Ajax Portlet Support
Weather Portlet Example

• Save location preferences via AJAX POST
• Return success or failure
Editing Portlet Preferences via Ajax
@RequestMapping(params = {"action=delete"})
public void deleteCity(
        @RequestParam(value = "locationCode") String locationCode,
        ActionRequest request, ActionResponse response) throws Exception {

    Map<Object, Object> model = new HashMap<Object, Object>();

    // remove location from preferences
    final PortletPreferences prefs = request.getPreferences();
    this.weatherService.deleteWeatherLocation(prefs, locationCode);

    // return success
    model.put("status", "success");
    this.ajaxPortletSupport
            .redirectAjaxResponse("ajax/json", model, request, response);
}
Ajax Response Controller
@Controller
public class AjaxResponseController {

    private AjaxPortletSupport ajaxPortletSupport;

    @Autowired
    public void setAjaxPortletSupport(
            AjaxPortletSupport ajaxPortletSupport) {
        this.ajaxPortletSupport = ajaxPortletSupport;
    }

    @RequestMapping("/json")
    public ModelAndView renderAjaxResponse(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletRequestBindingException, IOException {

        final Map<Object, Object> model = this.ajaxPortletSupport
                .getAjaxModel(request, response);

        return new ModelAndView("jsonView", model);
    }
}
Proxy an AJAX Target
Jasig Dictionary Portlet

• Uses Aonaware Dictionary XML REST service
• Want to make AJAX requests DictService server
• Single Origin Policy prevents request
  – need same protocol, domain, and port
Using Jasig’s ProxyView

@RequestMapping(method = RequestMethod.GET)
public ModelAndView getProxyView(HttpServletRequest request,
         @RequestParam(value="searchTerm") String searchTerm) {

    Map<String, Object> model = new HashMap<String, Object>();

    // build the URL to be proxied and add it to our model
    String url = “http://www.proxied.com/url”;
    model.put(ProxyView.URL, url.toString());

    // return a proxy view of the URL
    return new ModelAndView("proxyView", map);

}
Prevent Cross-side Scripting Attacks
Cross-Site Scripting
Unescaped Javascript


<script type="text/javascript">
    document.write('${title}');
</script>




<script type="text/javascript">
    document.write('' + alert('pwnd!') + '');
</script>
Escaped Javascript

<script type="text/javascript">
    document.write('<spring:escapeBody
     javaScriptEscape="true">${title}</spring:escapeBody>');
</script>




<script type="text/javascript">
    document.write('' + alert('pwnd!') + '');
</script>
Unescaped HTML


<h1>
    ${ title }
</h1>




<h1>
    <script type="text/javascript">alert('pwnd!');</script>
</h1>
Escaped HTML

<h1>
    <spring:escapeBody htmlEscape="true">
        ${ title }
    </spring:escapeBody>
</h1>




<h1>
    &lt;script type="text/javascript"&gt;alert
('pwnd!');&lt;/script&gt;
</h1>
XSS: Dictionary Portlet
// parse the definition from the response
in = get.getResponseBodyAsStream();
String def = service.getDefinitionFromXml(in);

// escape any HTML characters
return StringEscapeUtils.escapeHtml(def);
XSS: News Reader Portlet

• Display RSS feeds in a portlet
• Allow HTML, but maintain security
• Might need different policies for different sites
OWASP AntiSamy

• Java API for filtering HTML/CSS
• Define allowed tags and attributes through XML
• Clean input by stripping unwanted tags
  – strip malicious scripts from external content
  – improve presentation by removing images, etc.
News Reader: OWASP AntiSamy
// retrieve
InputStream in = get.getResponseBodyAsStream();

//parse
SyndFeed feed = input.build(new XmlReader(in));

//clean
AntiSamy as = new AntiSamy();

List<SyndEntry> a = feed.getEntries();

for (SyndEntry entry : a) {
    SyndContent description = entry.getDescription();

    Policy policy = Policy.getInstance(policyFile);

    CleanResults cr = as.scan(description.getValue(), policy);
    description.setValue(cr.getCleanHTML());
    entry.setDescription(description);
    log.info("Feed " + url + " cleaned in " +
            cr.getScanTime() + " seconds");

}
XSS: Calendar Portlet

• Custom AntiSamy JSP tag
• Wraps Spring-configured string cleaning utility

 <antisamy:clean value="${ event.description.value }"/>
AntiSamy-based String Cleaning

// clean a string using the configured AntiSamy file
public String getCleanString(String dirtyInput) throws ScanException,
                  PolicyException {

        AntiSamy as = new AntiSamy();
        CleanResults cr = as.scan(dirtyInput, this.policy);
        return cr.getCleanHTML();

}
AntiSamy-based JSP Tag
<%@ tag isELIgnored="false" dynamic-attributes="attributes" body-
content="empty" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ attribute name="value" required="true" %>
<%@ tag import="org.springframework.web.context.WebApplicationContext" %>
<%@ tag
import="org.springframework.web.context.support.WebApplicationContextUtils"
%>
<%@ tag import="org.jasig.portlet.calendar.util.StringCleaningUtil" %>
<%
    WebApplicationContext ctx =
        WebApplicationContextUtils.getWebApplicationContext(application);
    StringCleaningUtil util =
        (StringCleaningUtil) ctx.getBean("stringCleaningUtil");
%>
<%= util.getCleanString(value) %>
Preventing Non-Portlet Access

HttpSession session = request.getSession(false);
if (session == null ||
        !((Boolean) session.getAttribute("hasDictionarySession"))) {
    return new ModelAndView("jsonView", map);
}
Work with JSON and XML
Data as XML

• Javascript parsing
  – jQuery
• Java output and parsing
  – Maven JAXB plugin
  – XStream, etc.
• Groovy
Dictionary Parsing in Groovy
Groovy Implementation
   import java.io.InputStream
   import groovy.xml.StreamingMarkupBuilder
   import org.jasig.portlet.widget.service.IDictionaryParsingService

   class DictionaryParsingServiceImpl implements IDictionaryParsingService {

       String getDefinitionFromXml(InputStream xml) {
           def response = new XmlSlurper().parse(xml)
           return response.Definitions.Definition.WordDefinition
       }

   }



Spring Wiring
   <lang:groovy id="dictionaryParsingService"
   script-source="classpath:org/jasig/portlet/widget/service/
   DictionaryParsingServiceImpl.groovy"/>
Dictionary Parsing in Groovy
import java.io.InputStream
import groovy.xml.StreamingMarkupBuilder
import org.jasig.portlet.widget.service.IDictionaryParsingService

class DictionaryParsingServiceImpl implements IDictionaryParsingService {

    String getDefinitionFromXml(InputStream xml) {
        def response = new XmlSlurper().parse(xml)
        return response.Definitions.Definition.WordDefinition
    }

}
Data as JSON

• Javascript parsing
  – jQuery
• Java output and parsing
  – JSONlib
  – net.sf.json’s JsonView
JsonView
Controller code
    @RequestMapping("/json")
    public ModelAndView renderAjaxResponse(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletRequestBindingException, IOException {

        final Map<Object, Object> model = this.ajaxPortletSupport
                .getAjaxModel(request, response);

        return new ModelAndView("jsonView", model);
    }



views.xml
    <bean id="jsonView"
            class="net.sf.json.spring.web.servlet.view.JsonView">
        <property name="contentType" value="application/json" />
    </bean>



Response
    { response: success }
Present Different Views
Example: Calendar Portlet

• Three views
  – Mobile View
  – Narrow Column View
  – MAXIMIZED View

• Simple interface for view selection
M
         Calendar Views

                          Column




                          Maximized




Mobile
Calendar View Selection
public String getCalendarViewName(PortletRequest request) {
         String userAgent = request.getProperty("user-agent");

        // check to see if this is a mobile device
        if (this.mobileDeviceRegexes != null && userAgent != null) {
                 for (Pattern regex : this.mobileDeviceRegexes) {
                           if (regex.matcher(userAgent).matches()) {
                                    return CALENDAR_MOBILE_VIEW;
                           }
                 }
        }

        // otherwise check the portlet window state
        WindowState state = request.getWindowState();
        if (WindowState.MAXIMIZED.equals(state)) {
                 return CALENDAR_WIDE_VIEW;
        } else {
                 return CALENDAR_NARROW_VIEW;
        }

}
Mashups
Yale Maps Portlet
Example: SQL Query
Interesting Web APIs

• Google APIs
  – http://code.google.com/more/
• Yahoo APIs
  – http://developer.yahoo.com/everything.html#apis

• Programmable Web
  – http://www.programmableweb.com/apis

• Many Popular Sites
  – Twitter, YouTube, Last.fm
Personal Favorites

• Google Visualizations
• Google Maps
• Yahoo Stock Data
• Yahoo Weather
• Twitter
Looking Ahead
Spring 3.0

• Portlet 2.0 (JSR-286)
  – Resource URLs: @ResourceMapping
• Spring 3.0
  – REST template
  – JSR-286 support
Ajax in JSR-168 and Spring 2.5

JSP/Javascript
   $.get('<c:url value="/ajax/dictionary"/>', {}, function(){}, "json");




Servlet Controller
    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView getDefinition(HttpServletRequest request,
             @RequestParam(value="word") String word,
             @RequestParam(value="dictId") String dict) throws Exception {

         // stuff goes here
         return new ModelAndView("jsonView", map);

    }
Ajax with Jasig Library

JSP/Javascript
   $.get('${dictionaryUrl}', {}, function(){}, "json");




Portlet Controller
    @RequestMapping(params = {"action=delete"})
    public ModelAndView getDefinition(ActionRequest request,
            ActionResponse response, @RequestParam(value="word") String word,
            @RequestParam(value="dictId") String dict) throws Exception {

        // stuff goes here
        this.ajaxPortletSupport
                .redirectAjaxResponse("ajax/json", model, request, response);
    }
Ajax in JSR-286 and Spring 3.0

JSP/Javascript
   $.get('<portlet:resourceURL/>', {}, function(){}, "json");




Portlet Controller
    @ResourceMapping()
    public ModelAndView getDefinition(PortletRequest request,
             @RequestParam(value="word") String word,
             @RequestParam(value="dictId") String dict) throws Exception {

         // stuff goes here
         return new ModelAndView("jsonView", map);

    }
Example Resources
Presentation Examples

• Jasig Portlet Examples
  – Calendar Portlet
  – News Reader Portlet
  – Weather Portlet
  – Widget Portlets
    • Dictionary

• uPortal Examples
  – Portlet Administration Portlet
Questions?




    Jennifer Bourey
    jbourey@unicon.net
    www.unicon.net

Mais conteúdo relacionado

Mais procurados

Javatwo2012 java frameworkcomparison
Javatwo2012 java frameworkcomparisonJavatwo2012 java frameworkcomparison
Javatwo2012 java frameworkcomparisonJini Lee
 
HTML5 and CSS3 refresher
HTML5 and CSS3 refresherHTML5 and CSS3 refresher
HTML5 and CSS3 refresherIvano Malavolta
 
HTML5 and the dawn of rich mobile web applications pt 2
HTML5 and the dawn of rich mobile web applications pt 2HTML5 and the dawn of rich mobile web applications pt 2
HTML5 and the dawn of rich mobile web applications pt 2James Pearce
 
Introducing Rendr: Run your Backbone.js apps on the client and server
Introducing Rendr: Run your Backbone.js apps on the client and serverIntroducing Rendr: Run your Backbone.js apps on the client and server
Introducing Rendr: Run your Backbone.js apps on the client and serverSpike Brehm
 
Building Cross Platform Mobile Web Apps
Building Cross Platform Mobile Web AppsBuilding Cross Platform Mobile Web Apps
Building Cross Platform Mobile Web AppsJames Pearce
 
A Snapshot of the Mobile HTML5 Revolution
A Snapshot of the Mobile HTML5 RevolutionA Snapshot of the Mobile HTML5 Revolution
A Snapshot of the Mobile HTML5 RevolutionJames Pearce
 
Hyperproductive JSF 2.0 @ JavaOne Brazil 2010
Hyperproductive JSF 2.0 @ JavaOne Brazil 2010Hyperproductive JSF 2.0 @ JavaOne Brazil 2010
Hyperproductive JSF 2.0 @ JavaOne Brazil 2010Arun Gupta
 
HTML5: the new frontier of the web
HTML5: the new frontier of the webHTML5: the new frontier of the web
HTML5: the new frontier of the webIvano Malavolta
 
Plugins on OnDemand with Remote Apps - Atlassian Summit 2012
Plugins on OnDemand with Remote Apps - Atlassian Summit 2012 Plugins on OnDemand with Remote Apps - Atlassian Summit 2012
Plugins on OnDemand with Remote Apps - Atlassian Summit 2012 Atlassian
 
CQ Provisionning & Authoring
CQ Provisionning & AuthoringCQ Provisionning & Authoring
CQ Provisionning & AuthoringGabriel Walt
 
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 [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 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
 
Rest Security with JAX-RS
Rest Security with JAX-RSRest Security with JAX-RS
Rest Security with JAX-RSFrank Kim
 
A Complete Tour of JSF 2
A Complete Tour of JSF 2A Complete Tour of JSF 2
A Complete Tour of JSF 2Jim Driscoll
 
Uniface Lectures Webinar - Building Responsive Applications with Uniface: Dep...
Uniface Lectures Webinar - Building Responsive Applications with Uniface: Dep...Uniface Lectures Webinar - Building Responsive Applications with Uniface: Dep...
Uniface Lectures Webinar - Building Responsive Applications with Uniface: Dep...Uniface
 
Lecture 10 - Java Server Faces (JSF)
Lecture 10 - Java Server Faces (JSF)Lecture 10 - Java Server Faces (JSF)
Lecture 10 - Java Server Faces (JSF)Fahad Golra
 

Mais procurados (20)

Javatwo2012 java frameworkcomparison
Javatwo2012 java frameworkcomparisonJavatwo2012 java frameworkcomparison
Javatwo2012 java frameworkcomparison
 
HTML5 and CSS3 refresher
HTML5 and CSS3 refresherHTML5 and CSS3 refresher
HTML5 and CSS3 refresher
 
HTML5 and the dawn of rich mobile web applications pt 2
HTML5 and the dawn of rich mobile web applications pt 2HTML5 and the dawn of rich mobile web applications pt 2
HTML5 and the dawn of rich mobile web applications pt 2
 
Introducing Rendr: Run your Backbone.js apps on the client and server
Introducing Rendr: Run your Backbone.js apps on the client and serverIntroducing Rendr: Run your Backbone.js apps on the client and server
Introducing Rendr: Run your Backbone.js apps on the client and server
 
Building Cross Platform Mobile Web Apps
Building Cross Platform Mobile Web AppsBuilding Cross Platform Mobile Web Apps
Building Cross Platform Mobile Web Apps
 
Jsf presentation
Jsf presentationJsf presentation
Jsf presentation
 
A Snapshot of the Mobile HTML5 Revolution
A Snapshot of the Mobile HTML5 RevolutionA Snapshot of the Mobile HTML5 Revolution
A Snapshot of the Mobile HTML5 Revolution
 
Hyperproductive JSF 2.0 @ JavaOne Brazil 2010
Hyperproductive JSF 2.0 @ JavaOne Brazil 2010Hyperproductive JSF 2.0 @ JavaOne Brazil 2010
Hyperproductive JSF 2.0 @ JavaOne Brazil 2010
 
HTML5: the new frontier of the web
HTML5: the new frontier of the webHTML5: the new frontier of the web
HTML5: the new frontier of the web
 
Java server faces
Java server facesJava server faces
Java server faces
 
Plugins on OnDemand with Remote Apps - Atlassian Summit 2012
Plugins on OnDemand with Remote Apps - Atlassian Summit 2012 Plugins on OnDemand with Remote Apps - Atlassian Summit 2012
Plugins on OnDemand with Remote Apps - Atlassian Summit 2012
 
CQ Provisionning & Authoring
CQ Provisionning & AuthoringCQ Provisionning & Authoring
CQ Provisionning & Authoring
 
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
 
Introduction to jsf 2
Introduction to jsf 2Introduction to jsf 2
Introduction to jsf 2
 
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 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
 
Rest Security with JAX-RS
Rest Security with JAX-RSRest Security with JAX-RS
Rest Security with JAX-RS
 
A Complete Tour of JSF 2
A Complete Tour of JSF 2A Complete Tour of JSF 2
A Complete Tour of JSF 2
 
Uniface Lectures Webinar - Building Responsive Applications with Uniface: Dep...
Uniface Lectures Webinar - Building Responsive Applications with Uniface: Dep...Uniface Lectures Webinar - Building Responsive Applications with Uniface: Dep...
Uniface Lectures Webinar - Building Responsive Applications with Uniface: Dep...
 
Lecture 10 - Java Server Faces (JSF)
Lecture 10 - Java Server Faces (JSF)Lecture 10 - Java Server Faces (JSF)
Lecture 10 - Java Server Faces (JSF)
 

Semelhante a Rich Portlet Development in uPortal

Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen LjuSkills Matter
 
Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen LjuSkills Matter
 
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディングXitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディングscalaconfjp
 
Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014Ngoc Dao
 
ASP.NET Overview - Alvin Lau
ASP.NET Overview - Alvin LauASP.NET Overview - Alvin Lau
ASP.NET Overview - Alvin LauSpiffy
 
Easy Enterprise Integration Patterns with Apache Camel, ActiveMQ and ServiceMix
Easy Enterprise Integration Patterns with Apache Camel, ActiveMQ and ServiceMixEasy Enterprise Integration Patterns with Apache Camel, ActiveMQ and ServiceMix
Easy Enterprise Integration Patterns with Apache Camel, ActiveMQ and ServiceMixelliando dias
 
AnkaraJUG Kasım 2012 - PrimeFaces
AnkaraJUG Kasım 2012 - PrimeFacesAnkaraJUG Kasım 2012 - PrimeFaces
AnkaraJUG Kasım 2012 - PrimeFacesAnkara JUG
 
RichFaces: rich:* component library
RichFaces: rich:* component libraryRichFaces: rich:* component library
RichFaces: rich:* component libraryMax Katz
 
Primefaces Confess 2012
Primefaces Confess 2012Primefaces Confess 2012
Primefaces Confess 2012cagataycivici
 
Ride on the Fast Track of Web with Ruby on Rails- Part 2
Ride on the Fast Track of Web with Ruby on Rails- Part 2Ride on the Fast Track of Web with Ruby on Rails- Part 2
Ride on the Fast Track of Web with Ruby on Rails- Part 2A.K.M. Ahsrafuzzaman
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
RESTful Web Applications with Apache Sling
RESTful Web Applications with Apache SlingRESTful Web Applications with Apache Sling
RESTful Web Applications with Apache SlingBertrand Delacretaz
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Chris Alfano
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsFrancois Zaninotto
 
Repaso rápido a los nuevos estándares web
Repaso rápido a los nuevos estándares webRepaso rápido a los nuevos estándares web
Repaso rápido a los nuevos estándares webPablo Garaizar
 

Semelhante a Rich Portlet Development in uPortal (20)

Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen Lju
 
Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen Lju
 
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディングXitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
 
Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014
 
ASP.NET Overview - Alvin Lau
ASP.NET Overview - Alvin LauASP.NET Overview - Alvin Lau
ASP.NET Overview - Alvin Lau
 
Easy Enterprise Integration Patterns with Apache Camel, ActiveMQ and ServiceMix
Easy Enterprise Integration Patterns with Apache Camel, ActiveMQ and ServiceMixEasy Enterprise Integration Patterns with Apache Camel, ActiveMQ and ServiceMix
Easy Enterprise Integration Patterns with Apache Camel, ActiveMQ and ServiceMix
 
AnkaraJUG Kasım 2012 - PrimeFaces
AnkaraJUG Kasım 2012 - PrimeFacesAnkaraJUG Kasım 2012 - PrimeFaces
AnkaraJUG Kasım 2012 - PrimeFaces
 
Intro to JavaScript
Intro to JavaScriptIntro to JavaScript
Intro to JavaScript
 
RichFaces: rich:* component library
RichFaces: rich:* component libraryRichFaces: rich:* component library
RichFaces: rich:* component library
 
Primefaces Confess 2012
Primefaces Confess 2012Primefaces Confess 2012
Primefaces Confess 2012
 
Ride on the Fast Track of Web with Ruby on Rails- Part 2
Ride on the Fast Track of Web with Ruby on Rails- Part 2Ride on the Fast Track of Web with Ruby on Rails- Part 2
Ride on the Fast Track of Web with Ruby on Rails- Part 2
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Servlet 3.0
Servlet 3.0Servlet 3.0
Servlet 3.0
 
Html5 For Jjugccc2009fall
Html5 For Jjugccc2009fallHtml5 For Jjugccc2009fall
Html5 For Jjugccc2009fall
 
RESTful Web Applications with Apache Sling
RESTful Web Applications with Apache SlingRESTful Web Applications with Apache Sling
RESTful Web Applications with Apache Sling
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
Spine.js
Spine.jsSpine.js
Spine.js
 
Repaso rápido a los nuevos estándares web
Repaso rápido a los nuevos estándares webRepaso rápido a los nuevos estándares web
Repaso rápido a los nuevos estándares web
 

Mais de Jennifer Bourey

Migrating a 1M+ LOC project from AngularJS to Angular
Migrating a 1M+ LOC project from AngularJS to AngularMigrating a 1M+ LOC project from AngularJS to Angular
Migrating a 1M+ LOC project from AngularJS to AngularJennifer Bourey
 
Delivering Mobile Course Content with uMobile
Delivering Mobile Course Content with uMobileDelivering Mobile Course Content with uMobile
Delivering Mobile Course Content with uMobileJennifer Bourey
 
uMobile: Jasig-Sakai 2012
uMobile: Jasig-Sakai 2012uMobile: Jasig-Sakai 2012
uMobile: Jasig-Sakai 2012Jennifer Bourey
 
uMobile: Taking Mobile Applications and Devices to the Next Level
uMobile: Taking Mobile Applications and Devices to the Next LeveluMobile: Taking Mobile Applications and Devices to the Next Level
uMobile: Taking Mobile Applications and Devices to the Next LevelJennifer Bourey
 

Mais de Jennifer Bourey (7)

Migrating a 1M+ LOC project from AngularJS to Angular
Migrating a 1M+ LOC project from AngularJS to AngularMigrating a 1M+ LOC project from AngularJS to Angular
Migrating a 1M+ LOC project from AngularJS to Angular
 
Getting to Angular 2
Getting to Angular 2Getting to Angular 2
Getting to Angular 2
 
Delivering Mobile Course Content with uMobile
Delivering Mobile Course Content with uMobileDelivering Mobile Course Content with uMobile
Delivering Mobile Course Content with uMobile
 
uMobile: Jasig-Sakai 2012
uMobile: Jasig-Sakai 2012uMobile: Jasig-Sakai 2012
uMobile: Jasig-Sakai 2012
 
uMobile: Taking Mobile Applications and Devices to the Next Level
uMobile: Taking Mobile Applications and Devices to the Next LeveluMobile: Taking Mobile Applications and Devices to the Next Level
uMobile: Taking Mobile Applications and Devices to the Next Level
 
Sakai and uPortal 4
Sakai and uPortal 4Sakai and uPortal 4
Sakai and uPortal 4
 
uPortal 3.2 And Beyond
uPortal 3.2 And BeyonduPortal 3.2 And Beyond
uPortal 3.2 And Beyond
 

Último

The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...itnewsafrica
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 

Último (20)

The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 

Rich Portlet Development in uPortal

  • 1. Rich Portlet Development Jennifer Bourey Jasig Spring Conference, March 9, 2010 © Copyright Unicon, Inc., 2006. This work is the intellectual property of Unicon, Inc. Permission is granted for this material to be shared for non- commercial, educational purposes, provided that this copyright statement appears on the reproduced materials and notice is given that the copying is by permission of Unicon, Inc. To disseminate otherwise or to republish requires written permission from Unicon, Inc.
  • 2. Portlet Development Goals • Make – life easier – development faster – portlets shinier
  • 3. Create an Accessible 2-Column Layout
  • 5. Using the Fluid Skinning System <div class="fl-col-flex2"> <!-- start: left panel --> <div class="fl-col"> <h1>I'm the left column!</h1> </div><!-- end: left panel --> <!-- start: right panel --> <div class="fl-col"> <h1>I'm the right column!</h1> </div><!-- end: right panel --> </div>
  • 6. Accessible Two-Column Layout fl-col fl-col fl-col-flex2
  • 7. Fluid Skinning System • Layout wrappers and containers • Convenience classnames – GUI elements: Tabs, menus, icons, widgets – font family, size, and formatting • Theming • Accessibility – easy page linearization – tested for usabiltity effectiveness, specifically colorblindness – works with Assistive Technology
  • 8. Allow Users to Page Through a List
  • 10. More from Fluid Infusion • Components – Pager – Reorderers (list, grid, and image) – Uploader – Progressbar – Inline text edit • http://fluidproject.org/releases/1.1.2/demos/
  • 11. Allow Users to Select a Date
  • 13. jQuery UI Datepicker <div> <label>Start date:</label> <input class="cal-datepicker"></input> </div> <script type="text/javascript"> $(document).ready(function(){ $(".cal-datepicker").datepicker(); }); </script>
  • 14. jQuery UI Widgets • Widgets – Accordion – Datepicker – Dialog – Progressbar – Slider – Tabs • Demos: http://jqueryui.com/demos/
  • 17. jQuery UI • Effects – show, hide, toggle, color animation – add/remove/toggle/switch css class • Demos: http://jqueryui.com/demos/
  • 19. Improve UI Performance • Minify code • Minimize HTTP requests • Apply cache headers • GZip resources
  • 20. Jasig Resource Server • Server Webapp – Library of popular CSS, JS, and image resources – Provide consistent URLs – Cache, minify, and gzip hosted resources • Utilities – Filters for caching and gzipping – JSP tag for including files from resource server • Bundled with uPortal 3.1+
  • 21. Minify code: YUI Maven Plugin <plugin> <groupId>net.sf.alchim</groupId> <artifactId>yuicompressor-maven-plugin</artifactId> <version>0.7.1</version> <executions> <execution> <goals><goal>compress</goal></goals> </execution> </executions> <configuration> <excludes> <exclude>**/*.min.js</exclude> </excludes> <linebreakpos>10000</linebreakpos> <suffix>.min</suffix> <jswarn>false</jswarn> </configuration> </plugin>
  • 22. Cache Headers: Resource Server <filter> <filter-name>CacheExpiresFilter</filter-name> <filter-class> org.jasig.resourceserver.utils.filter.CacheExpirationFilter </filter-class> <!-- Length of time to set in cache headers (in seconds) --> <init-param> <param-name>cacheMaxAge</param-name> <param-value>31536000</param-value> </init-param> <!-- Time between regenerating cache header strings (in millis) --> <init-param> <param-name>regenerateHeadersInterval</param-name> <param-value>1000</param-value> </init-param> </filter> <filter-mapping> <filter-name>CacheExpiresFilter</filter-name> <url-pattern>/rs/*</url-pattern> </filter-mapping>
  • 23. GZip CSS and JS <filter> <filter-name>pageCachingFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</ filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>pageCachingFilter</filter-name> <url-pattern>*.js</url-pattern> </filter-mapping> <filter-mapping> <filter-name>pageCachingFilter</filter-name> <url-pattern>*.css</url-pattern> </filter-mapping>
  • 24. GZip CSS and JS <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="cacheManagerName" value="ResourceServer.cacheManager" /> </bean> <bean id="pageCachingFilter" class="org.jasig.resourceserver.utils.cache.ConfigurablePageCachingFilter"> <constructor-arg ref="cacheManager"/> <constructor-arg value="SimplePageCachingFilter"/> </bean>
  • 25. GZip HTML: Tomcat <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" emptySessionPath="true" compression="on" compressableMimeType="text/html,text/xml,text/plain" />
  • 27. After
  • 28. Interact with Portlet Session and Preferences via AJAX
  • 29. AJAX Servlet Portlet Controller Browser Servlet Controller No portlet preferences access No portlet session access
  • 30. Jasig Ajax Portlet Support Portlet Browser Controller Servlet Controller
  • 32. Weather Portlet Example • Save location preferences via AJAX POST • Return success or failure
  • 33. Editing Portlet Preferences via Ajax @RequestMapping(params = {"action=delete"}) public void deleteCity( @RequestParam(value = "locationCode") String locationCode, ActionRequest request, ActionResponse response) throws Exception { Map<Object, Object> model = new HashMap<Object, Object>(); // remove location from preferences final PortletPreferences prefs = request.getPreferences(); this.weatherService.deleteWeatherLocation(prefs, locationCode); // return success model.put("status", "success"); this.ajaxPortletSupport .redirectAjaxResponse("ajax/json", model, request, response); }
  • 34. Ajax Response Controller @Controller public class AjaxResponseController { private AjaxPortletSupport ajaxPortletSupport; @Autowired public void setAjaxPortletSupport( AjaxPortletSupport ajaxPortletSupport) { this.ajaxPortletSupport = ajaxPortletSupport; } @RequestMapping("/json") public ModelAndView renderAjaxResponse(HttpServletRequest request, HttpServletResponse response) throws ServletRequestBindingException, IOException { final Map<Object, Object> model = this.ajaxPortletSupport .getAjaxModel(request, response); return new ModelAndView("jsonView", model); } }
  • 35. Proxy an AJAX Target
  • 36. Jasig Dictionary Portlet • Uses Aonaware Dictionary XML REST service • Want to make AJAX requests DictService server • Single Origin Policy prevents request – need same protocol, domain, and port
  • 37. Using Jasig’s ProxyView @RequestMapping(method = RequestMethod.GET) public ModelAndView getProxyView(HttpServletRequest request, @RequestParam(value="searchTerm") String searchTerm) { Map<String, Object> model = new HashMap<String, Object>(); // build the URL to be proxied and add it to our model String url = “http://www.proxied.com/url”; model.put(ProxyView.URL, url.toString()); // return a proxy view of the URL return new ModelAndView("proxyView", map); }
  • 40. Unescaped Javascript <script type="text/javascript"> document.write('${title}'); </script> <script type="text/javascript"> document.write('' + alert('pwnd!') + ''); </script>
  • 41. Escaped Javascript <script type="text/javascript"> document.write('<spring:escapeBody javaScriptEscape="true">${title}</spring:escapeBody>'); </script> <script type="text/javascript"> document.write('' + alert('pwnd!') + ''); </script>
  • 42. Unescaped HTML <h1> ${ title } </h1> <h1> <script type="text/javascript">alert('pwnd!');</script> </h1>
  • 43. Escaped HTML <h1> <spring:escapeBody htmlEscape="true"> ${ title } </spring:escapeBody> </h1> <h1> &lt;script type="text/javascript"&gt;alert ('pwnd!');&lt;/script&gt; </h1>
  • 44. XSS: Dictionary Portlet // parse the definition from the response in = get.getResponseBodyAsStream(); String def = service.getDefinitionFromXml(in); // escape any HTML characters return StringEscapeUtils.escapeHtml(def);
  • 45. XSS: News Reader Portlet • Display RSS feeds in a portlet • Allow HTML, but maintain security • Might need different policies for different sites
  • 46. OWASP AntiSamy • Java API for filtering HTML/CSS • Define allowed tags and attributes through XML • Clean input by stripping unwanted tags – strip malicious scripts from external content – improve presentation by removing images, etc.
  • 47. News Reader: OWASP AntiSamy // retrieve InputStream in = get.getResponseBodyAsStream(); //parse SyndFeed feed = input.build(new XmlReader(in)); //clean AntiSamy as = new AntiSamy(); List<SyndEntry> a = feed.getEntries(); for (SyndEntry entry : a) { SyndContent description = entry.getDescription(); Policy policy = Policy.getInstance(policyFile); CleanResults cr = as.scan(description.getValue(), policy); description.setValue(cr.getCleanHTML()); entry.setDescription(description); log.info("Feed " + url + " cleaned in " + cr.getScanTime() + " seconds"); }
  • 48. XSS: Calendar Portlet • Custom AntiSamy JSP tag • Wraps Spring-configured string cleaning utility <antisamy:clean value="${ event.description.value }"/>
  • 49. AntiSamy-based String Cleaning // clean a string using the configured AntiSamy file public String getCleanString(String dirtyInput) throws ScanException, PolicyException { AntiSamy as = new AntiSamy(); CleanResults cr = as.scan(dirtyInput, this.policy); return cr.getCleanHTML(); }
  • 50. AntiSamy-based JSP Tag <%@ tag isELIgnored="false" dynamic-attributes="attributes" body- content="empty" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ attribute name="value" required="true" %> <%@ tag import="org.springframework.web.context.WebApplicationContext" %> <%@ tag import="org.springframework.web.context.support.WebApplicationContextUtils" %> <%@ tag import="org.jasig.portlet.calendar.util.StringCleaningUtil" %> <% WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(application); StringCleaningUtil util = (StringCleaningUtil) ctx.getBean("stringCleaningUtil"); %> <%= util.getCleanString(value) %>
  • 51. Preventing Non-Portlet Access HttpSession session = request.getSession(false); if (session == null || !((Boolean) session.getAttribute("hasDictionarySession"))) { return new ModelAndView("jsonView", map); }
  • 52. Work with JSON and XML
  • 53. Data as XML • Javascript parsing – jQuery • Java output and parsing – Maven JAXB plugin – XStream, etc. • Groovy
  • 54. Dictionary Parsing in Groovy Groovy Implementation import java.io.InputStream import groovy.xml.StreamingMarkupBuilder import org.jasig.portlet.widget.service.IDictionaryParsingService class DictionaryParsingServiceImpl implements IDictionaryParsingService { String getDefinitionFromXml(InputStream xml) { def response = new XmlSlurper().parse(xml) return response.Definitions.Definition.WordDefinition } } Spring Wiring <lang:groovy id="dictionaryParsingService" script-source="classpath:org/jasig/portlet/widget/service/ DictionaryParsingServiceImpl.groovy"/>
  • 55. Dictionary Parsing in Groovy import java.io.InputStream import groovy.xml.StreamingMarkupBuilder import org.jasig.portlet.widget.service.IDictionaryParsingService class DictionaryParsingServiceImpl implements IDictionaryParsingService { String getDefinitionFromXml(InputStream xml) { def response = new XmlSlurper().parse(xml) return response.Definitions.Definition.WordDefinition } }
  • 56. Data as JSON • Javascript parsing – jQuery • Java output and parsing – JSONlib – net.sf.json’s JsonView
  • 57. JsonView Controller code @RequestMapping("/json") public ModelAndView renderAjaxResponse(HttpServletRequest request, HttpServletResponse response) throws ServletRequestBindingException, IOException { final Map<Object, Object> model = this.ajaxPortletSupport .getAjaxModel(request, response); return new ModelAndView("jsonView", model); } views.xml <bean id="jsonView" class="net.sf.json.spring.web.servlet.view.JsonView"> <property name="contentType" value="application/json" /> </bean> Response { response: success }
  • 59. Example: Calendar Portlet • Three views – Mobile View – Narrow Column View – MAXIMIZED View • Simple interface for view selection
  • 60. M Calendar Views Column Maximized Mobile
  • 61. Calendar View Selection public String getCalendarViewName(PortletRequest request) { String userAgent = request.getProperty("user-agent"); // check to see if this is a mobile device if (this.mobileDeviceRegexes != null && userAgent != null) { for (Pattern regex : this.mobileDeviceRegexes) { if (regex.matcher(userAgent).matches()) { return CALENDAR_MOBILE_VIEW; } } } // otherwise check the portlet window state WindowState state = request.getWindowState(); if (WindowState.MAXIMIZED.equals(state)) { return CALENDAR_WIDE_VIEW; } else { return CALENDAR_NARROW_VIEW; } }
  • 65. Interesting Web APIs • Google APIs – http://code.google.com/more/ • Yahoo APIs – http://developer.yahoo.com/everything.html#apis • Programmable Web – http://www.programmableweb.com/apis • Many Popular Sites – Twitter, YouTube, Last.fm
  • 66. Personal Favorites • Google Visualizations • Google Maps • Yahoo Stock Data • Yahoo Weather • Twitter
  • 68. Spring 3.0 • Portlet 2.0 (JSR-286) – Resource URLs: @ResourceMapping • Spring 3.0 – REST template – JSR-286 support
  • 69. Ajax in JSR-168 and Spring 2.5 JSP/Javascript $.get('<c:url value="/ajax/dictionary"/>', {}, function(){}, "json"); Servlet Controller @RequestMapping(method = RequestMethod.GET) public ModelAndView getDefinition(HttpServletRequest request, @RequestParam(value="word") String word, @RequestParam(value="dictId") String dict) throws Exception { // stuff goes here return new ModelAndView("jsonView", map); }
  • 70. Ajax with Jasig Library JSP/Javascript $.get('${dictionaryUrl}', {}, function(){}, "json"); Portlet Controller @RequestMapping(params = {"action=delete"}) public ModelAndView getDefinition(ActionRequest request, ActionResponse response, @RequestParam(value="word") String word, @RequestParam(value="dictId") String dict) throws Exception { // stuff goes here this.ajaxPortletSupport .redirectAjaxResponse("ajax/json", model, request, response); }
  • 71. Ajax in JSR-286 and Spring 3.0 JSP/Javascript $.get('<portlet:resourceURL/>', {}, function(){}, "json"); Portlet Controller @ResourceMapping() public ModelAndView getDefinition(PortletRequest request, @RequestParam(value="word") String word, @RequestParam(value="dictId") String dict) throws Exception { // stuff goes here return new ModelAndView("jsonView", map); }
  • 73. Presentation Examples • Jasig Portlet Examples – Calendar Portlet – News Reader Portlet – Weather Portlet – Widget Portlets • Dictionary • uPortal Examples – Portlet Administration Portlet
  • 74. Questions? Jennifer Bourey jbourey@unicon.net www.unicon.net