Your SlideShare is downloading. ×
0
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
JavaServer Faces Anti-Patterns and Pitfalls
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

JavaServer Faces Anti-Patterns and Pitfalls

2,645

Published on

Here are my slides from ApacheCon 2007

Here are my slides from ApacheCon 2007

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,645
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
92
Comments
0
Likes
3
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. JavaServer Faces Anti-Patterns Dennis Byrne - ThoughtWorks [email_address] http://notdennisbyrne.blogspot.com
  • 2. Validating Setter
      • <managed-bean>
      • <managed-bean-name>iterationBean</managed-bean-name>
      • <managed-bean-class> com.thoughtworks.Iteration
      • </managed-bean-class>
      • <managed-bean-scope> request </managed-bean-scope>
      • <managed-property>
      • <property-name> start </property-name>
      • <value> #{sprintBean.currentStart} </value>
      • </managed-property>
      • <managed-property>
      • <property-name> end </property-name>
      • <value> #{sprintBean.currentEnd} </value>
      • </managed-property>
      • <managed-property>
      • <property-name>last</property-name>
      • <value>hack</value>
      • </managed-property>
      • </managed-bean>
  • 3. Validating Setter
    • public class Iteration {
    • private Calendar start, end; // injected
    • // sans setters and getters for start, end
    • public void setLast(String last) {
    • if(start == null)
    • throw new NullPointerException(&quot;start&quot;);
    • if(end == null)
    • throw new NullPointerException(&quot;end&quot;);
    • if(start.after(end))
    • throw new IllegalStateException(&quot;start > end&quot;);
    • }
    • }
  • 4. Validating Setter Solutions
    • <application>
    • <variable-resolver>
    • org.springframework.web.jsf.DelegatingVariableResolver
    • </variable-resolver>
    • </application>
    • <application> <el-resolver>
    • org.apache.myfaces.el.unified.resolver.GuiceResolver
    • </el-resolver>
    • </application>
    • public class Iteration {
    • private Calendar start, end; // injected
    • @PostConstruct
    • public void initialize() {
    • // domain validation logic here ...
    • }
    • }
  • 5. The Map Trick
    • #{requestScopedMap.key} // calls get(‘key’)
    • #{requestScopedMap[‘key’]}
    • public class MapTrick implements java.util.Map {
    • public Object get(Object key) {
    • return new BusinessLogic().doSomething(key);
    • }
    • public void clear() { }
    • public boolean containsKey(Object arg) { return false; }
    • public boolean isEmpty() { return false; }
    • public Set keySet() { return null; }
    • public Object put(Object key, Object value) { return null; }
    • public void putAll(Map arg) { }
    • public Object remove(Object arg) { return null; }
    • public int size() { return 0; }
    • }
  • 6. déjà vu PhaseListener
      • <context-param>
      • <description>
      • comma separated list of JSF conf files
      • </description>
      • <param-name> javax.faces.CONFIG_FILES </param-name>
      • <param-value>
      • /WEB-INF/faces-config.xml
      • </param-value>
      • </context-param>
      • <lifecycle>
      • <phase-listener>
      • com.thoughtworks.PhaseListenerImpl
      • </phase-listener>
      • </lifecycle>
  • 7. XML Hell
      • <navigation-rule> <from-view-id>/home.xhtml</from-view-id>
      • <navigation-case>
      • <from-outcome>contact_us</from-outcome>
      • <to-view-id>/contact.xhtml</to-view-id>
      • </navigation-case>
      • </navigation-rule>
      • <navigation-rule> <from-view-id>/site_map.xhtml</from-view-id>
      • <navigation-case>
      • <from-outcome>contact_us</from-outcome>
      • <to-view-id>/contact.xhtml</to-view-id>
      • </navigation-case>
      • </navigation-rule>
      • <navigation-rule><from-view-id> * </from-view-id>
      • <navigation-case> <!-- global nav rule -->
      • <from-outcome>contact_us</from-outcome>
      • <to-view-id>/contact.xhtml</to-view-id>
      • </navigation-case>
      • </navigation-rule>
  • 8. Thread Safety
        • javax.faces.event.PhaseListener
        • javax.faces.render.Renderer
        • Managed Beans
        • javax.faces.convert.Converter
        • javax.faces.validator.Validator
        • javax.faces.FacesContext
        • JSF Tags
  • 9. Thread Safety
    • <h:inputText value=&quot;#{managedBean.value}&quot; converter=&quot;#{threadUnsafe}&quot; />
    • <managed-bean>
    • <managed-bean-name>threadUnsafe</managed-bean-name>
    • <managed-bean-class>
    • org.apache.myfaces.book.ThreadUnsafeConverter
    • </managed-bean-class>
    • <managed-bean-scope> session </managed-bean-scope>
    • </managed-bean>
    • <h:inputText value=&quot;#{managedBean.value}&quot; >
    • <f:converter converterId=&quot;threadUnsafe&quot; > <!-- Always Safe -->
    • </h:inputText>
    • <converter>
    • <converter-id>threadUnsafe</converter-id>
    • <converter-class>org.apache.myfaces.book.ThreadUnsafeConverter
    • </converter-class>
    • </converter>
  • 10. Facelets Migration
    • public class WidgetTag extends UIComponentELTag{
    • private String title, styleClass = &quot;default_class&quot;;
    • protected void setProperties(UIComponent component) {
    • super.setProperties(component);
    • Widget span = (Widget) component;
    • span.setStyleClass(styleClass);
    • span.setTitle(title == null ? &quot;no title&quot; : title);
    • FacesContext ctx = FacesContext.getCurrentInstance();
    • Map session = ctx.getExternalContext().getSessionMap();
    • span.setStyle((String) session.get(&quot;style&quot;));
    • }
    • }
  • 11. Law of Demeter
    • A “Train Wreck” - sensitive to changes in domain model
    • employee. getDepartment().getManager()
    • .getOffice().getAddress().getZip();
    • An EL “Train Wreck” - sensitive to changes in domain model
    • #{employee. department.manager.office.address.zip }
    • Encapsulated, insensitive to changes in domain model
    • #{employee.officeManagersZipCode}
  • 12. Vendor Lock-in
    • import org.apache.myfaces.component.html.ext.HtmlInputHidden;
    • import org.apache.myfaces.component.html.ext.HtmlInputText;
    • import org.apache.myfaces.component.html.ext.HtmlOutputText;
    • public class ImplementationDependentManagedBean {
      • private HtmlInputText input ;
      • private HtmlInputHidden hidden ;
      • private HtmlOutputText output ;
      • /* getters and setters omitted */
      • public boolean recordTotal(ActionEvent event) {
      • long total = ((Long)input.getValue()).longValue();
      • total += ((Long)hidden.getValue()).longValue();
      • total += ((Long)output.getValue()).longValue();
      • return new JmsUtil().broadcastTotal(total);
      • }
    • }
  • 13. Vendor Lock-in Solution
    • import javax.faces.component.ValueHolder;
    • public class RefactoredManagedBean {
    • private ValueHolder input ;
    • private ValueHolder hidden ;
    • private ValueHolder output ;
    • /* getters & setters ommitted */
    • public boolean recordTotal(ActionEvent event) {
    • long total = 0;
    • ValueHolder[] vh = new ValueHolder[] {input, hidden, output};
    • for(ValueHolder valued : vh)
    • total += ((Long)valued.getValue()).longValue();
    • return new JmsUtil().broadcastTotal(total);
    • }
    • }
  • 14. Portlet ClassCastException
    • FacesContext ctx = FacesContext.getCurrentInstance();
    • ExternalContext ectx = ctx.getExternalContext();
    • ServletRequest request = ( ServletRequest )ectx .getRequest();
    • String id = request.getParameter(&quot;id&quot;);
    • FacesContext ctx = FacesContext.getCurrentInstance();
    • ExternalContext ectx = ctx.getExternalContext();
    • String id = ectx.getRequestParameterMap().get(&quot;id&quot;);
  • 15. OpenTransactionInViewFilter
      • public void doFilter(ServletRequest request,
    • ServletResponse response, FilterChain chain){
      • try {
      • ObjectRelationalUtility.startTransaction();
      • chain.doFilter(request, response);
      • ObjectRelationalUtility.commitTransaction();
      • } catch (Throwable throwable) {
      • try {
      • ObjectRelationalUtility.rollbackTransaction();
      • } catch (Throwable _throwable) {
      • /* sans error handling */
      • }
      • }
      • }
  • 16. N + 1
      • <!-- One trip to the database for the master record ... -->
      • <h:dataTable value=&quot;#{projectBean.projects}&quot; var=&quot;project&quot;>
      • <h:column>
      • <h:commandLink action=&quot;#{projectBean.viewProject}&quot;
      • value=&quot;view project&quot;/>
      • </h:column>
      • <h:column>
      • <!-- ... and + N trips for each child record -->
      • <f:facet name=&quot;header&quot;>Project Manager</f:facet>
      • #{project .manager.name }
      • </h:column>
      • <h:column>
      • <f:facet name=&quot;header&quot;>Project Name</f:facet>
      • #{project.name}
      • </h:column>
      • </h:dataTable>
  • 17. N + 1- N
    • public class OpenTransactionInApplicationPhaseListener
    • implements PhaseListener {
    • public void beforePhase(PhaseEvent event) {
    • try {
    • ObjectRelationalUtility.startTransaction();
    • } catch (Throwable throwable) { /* sans error handling */ }
    • }
    • public void afterPhase(PhaseEvent event) {
    • try {
    • ObjectRelationalUtility.commitTransaction();
    • } catch (Throwable throwable) {
    • ObjectRelationalUtility.rollbackTransaction();
    • }
    • }
    • public PhaseId getPhaseId(){return PhaseId.INVOKE_APPLICATION ;}
    • }
  • 18. Thanks
    • Dennis Byrne - ThoughtWorks
    • [email_address]
    • http://notdennisbyrne.blogspot.com

×