Announcement Announcement Module
Collapse
No announcement yet.
Issues trying to create a "ConnectedToProvider" JSP Tag... Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Issues trying to create a "ConnectedToProvider" JSP Tag...

    This is possibly OT, but since I'm working on in the context of SpringSocial figured I'd try to get some help here first.

    In the Spring Social Showcase you have a ConnectedToHandlerInterceptor that looks like on every request will check to see if you if you have connections for facebook and twitter.

    The majority of the time I'd think you'd need to know this only on the front-end and typically on only certain pages ( eg maybe on the main page you want to show the "connect with facebook" button if you haven't done so, but this only appears on one page.)

    I'm using Spring 3.0.6 and when creating a tag for this so that the ConnectionRepository could be injected has been proving difficult.

    I end up with an error on startup:

    Code:
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.connectionRepository': Scope '
    request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton;
     nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an a
    ctual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request an
    d still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContext
    Listener or RequestContextFilter to expose the current request.
    I tried adding RequestContextListener to web.xml but that didn't seem to help. Is it going to be too difficult to create a Tag to do what I want, or am I just missing something simple?

    Here is what I'm currently attempting:

    bean declaration:
    Code:
    <bean class="com.foocompany.web.taglib.social.SocialConnectedTag">
            <property name="connectionRepository" ref="connectionRepository"/>
    </bean>
    tag: (note: not my idea to use java.util.logging...sadly the project is already entrenched with it
    Code:
    @Configurable
    public class SocialConnectedTag extends SimpleTagSupport {
        private final static Logger logger = Logger.getLogger(SocialConnectedTag.class.getName());
    
        //tag attribute
        private String provider;
        //set from spring
        private ConnectionRepository connectionRepository;
    
        @Override
        public void doTag() throws JspException, IOException {
            if (!provider.equals("facebook") && !provider.equals("twitter")) {
                logger.severe("Provider: "+provider+" passed to SocialConnectedTag and is not a valid provider");
                return;
            }
    
            if (connectionRepository.findConnections(provider).size() > 0) {
                StringWriter sw = new StringWriter();
                getJspBody().invoke(sw);
                JspWriter out = getJspContext().getOut();
                out.println(sw.toString());
            }
        }
    
        public void setProvider(String provider) {
            this.provider = provider;
        }
    
        public void setConnectionRepository(ConnectionRepository connectionRepository) {
             this.connectionRepository = connectionRepository;
        }
    }
    Sample usage (tld exists just not showing it.)

    Code:
    <social:connected provider="facebook">You're connected to facebook</social:connected>

  • #2
    I like your thinking here that a JSP tag would be useful in determining if a user is connected to a given provider. I can imagine that being quite useful.

    But using @Configurable to get the connection factory into the tag is troubling to me because @Configurable requires additional setup and I'd like to use a JSP tag as-is without having to do any Spring wiring of the tag or making sure that the AspectJ stuff that @Configurable needs is in place.

    Instead of injecting the connection factory into the tag, why not have the tag retrieve it from the application context? I just threw this together quickly (e.g., there is likely room for improvement), but it seems to do what you want without any additional configuration of the tag (aside from the TLD):

    Code:
    package org.springframework.social.showcase.jsp;
    import org.springframework.social.connect.ConnectionRepository;
    import org.springframework.web.context.WebApplicationContext;
    import org.springframework.web.servlet.tags.RequestContextAwareTag;
    
    public class SocialConnectedTag extends RequestContextAwareTag {
    	//tag attribute
    	private String provider;
    
    	@Override
    	protected int doStartTagInternal() throws Exception {
        	if (supportsProvider(provider) && getConnectionRepository().findConnections(provider).size() > 0) {
                return EVAL_BODY_INCLUDE;        	
            }
            
            return SKIP_BODY;
    	}
        
    	public void setProvider(String provider) {
    		this.provider = provider;
    	}
    
    	private ConnectionRepository getConnectionRepository() {
    		WebApplicationContext applicationContext = getRequestContext().getWebApplicationContext();
    		return applicationContext.getBean(ConnectionRepository.class);
    	}
    	
    	private boolean supportsProvider(String provider) {
    		return provider.equals("facebook") || provider.equals("twitter");
    	}
    }
    Let me know what you think. And again, I just tossed this together in a couple of minutes, so if you see any potential improvements, post them here.

    Comment


    • #3
      Beautiful! Works perfectly. (Funny I was googling for how to best do this and never even ran across Spring's RequestContextAwareTag - very nice!)

      Am I correct in my assumption that this could be useful in two ways:
      1) Prevents every request from having to make a check if you are connected to providers( via the interceptor)
      2) Useful because even with the interceptor, it's possible certain controllers could do some redirects and you'd lose the request attribute (and not sure I'd want to store it in the session.) This way any view could have access to whether you are connected or not. (In our real-life case, we'll want to show the "Connect to Facebook" button on the main site on certain pages.

      [ side note: since you might be aware from other threads that I'm also working on a facebook app that will always show in a canvas - this is a different work flow. Basically we'll have one version of the site that is 'standard' but you still might want to connect with facebook etc. Another version of the site slightly different UI will be presented as a facebook app embedded in an iframe - in that latter case of course the "connect to facebook' button wont' be necessary.]

      Thanks again. This tag is great. (It could even be used in the spring social showcase for the menu items display in place of relying on the interceptor.)

      Comment

      Working...
      X