[PORTLETSPEC3-40] Add new javax.portlet.ResourceComparator annotation in order to identify duplicate resources Created: 13/Dec/13  Updated: 13/May/14

Status: Open
Project: portletspec3
Component/s: Ideas for JSR 362 Extensions
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: Neil Griffin Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

I would like to propose the following annotation, which
would allow portlet developers (and JSF portlet bridge implementors)
to provide a way to inform the portlet container of duplicate
resources. This is a common problem with JSF portlets, since each
JSF portlet on the portal page needs the "jsf.js" resource:

package javax.portlet;
/**
* Annotation for marking a class that compares resource URLs. Such classes are
* discovered by the portlet container at startup and are required to
* implement the {@link java.util.Comparator} interface in order to compare
* resources represented as type {@link java.lang.String}. If the
* {@link java.util.Comparator#compare(Object, Object)} method returns 0, then
* the portlet container will consider the resources to be identical and will include
* only the first resource in the <head/> section of the rendered portal page.
*
* @since 3.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ResourceComparator {
}

Here is an example that a JSF portlet bridge could use in order to prevent duplicate JSF resources:

public interface FacesResource {

	public enum TYPE {
		HREF, LINK, SCRIPT
	}
	
	public TYPE getType();
	
	public String getName();
	
	public String getLibrary();
}
@ResourceComparator
public class FacesResourceComparator implements Comparator<String> {

	public int compare(String resourceURL1, String resourceURL2) {

		if (isFacesResource(resourceURL1) && isFacesResource(resourceURL2)) {
				
				FacesResource facesResource1 = new FacesResourceImpl(resourceURL1);
				FacesResource facesResource2 = new FacesResourceImpl(resourceURL2);

				if (facesResource1.equals(facesResource2)) {
					return 0;
				}
				else {
					return -1;
				}
		}
		else {
			return -1;
		}
	}

	protected boolean isFacesResource(String url) {
		return ((url != null) && url.contains("javax.faces.resource"));
	}
}


 Comments   
Comment by kito75 [ 14/Jan/14 ]

Sounds good to me. Would we need a default implementation?

Comment by Ed Burns [ 13/May/14 ]

This seems like a tough problem to solve in the absence of a component based rendering model.

Comment by Ed Burns [ 13/May/14 ]

I would need to see more context to be able to critique this. I don't know enough about the portlet runtime to understand who would be instantiating the FacesResourceComparator and when it would be getting invoked, for example.

Comment by Neil Griffin [ 13/May/14 ]

After each portlet on a page has undergone the RENDER_PHASE of the portlet lifecycle, the portal server is responsible for assembling a complete HTML document. When it comes time for the portal server to build up the contents of the <head>...</head> section, the portal server would invoke classes marked with @ResourceComparator in order to let individual portlets determine whether or not two resources are essentially identical. One example would be a portal page with two or more JSF portlets. Each JSF portlet would attempt to add jsf.js to the <head>...</head> section. The JSF Portlet Bridge could have a class annotated with @ResourceComparator that would be able to identify duplicate jsf.js inclusions. The portal server would then know that it should only include the first instance of jsf.js in the <head>...</head> section.

Generated at Wed May 06 06:46:59 UTC 2015 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.