Tom
Tom

Reputation: 2847

How to write tag in my spring project?

I want to write my tag (extends TagSupport) in my spring framework. In my tag class, will use some service which should auto inject by spring. But I always get null, seems spring can't inject service instance in my tag class.

The code is like the following:

public class FetchTagNameTag extends TagSupport {

   @Autowired
   private TaskService taskService;
   ...

taskService is always null.

How can I resolve this? Thanks.

Upvotes: 8

Views: 6859

Answers (7)

Nitesh Tripathi
Nitesh Tripathi

Reputation: 1

Use :-

import org.springframework.web.servlet.tags.RequestContextAwareTag;

public class FetchTagNameTag extends RequestContextAwareTag {

//   @Autowired

  // private TaskService taskService;

   @Override

    protected int doStartTagInternal() throws Exception {

TaskService taskService=  getRequestContext().getWebApplicationContext().getBean(TaskService.class);


    return 0;
   }

Upvotes: 0

msangel
msangel

Reputation: 10362

First I write this:

public abstract class SpringSuportedTag  extends SimpleTagSupport{

protected WebApplicationContext _applicationContext;

protected WebApplicationContext getSpringContext(){
    PageContext pageContext = (PageContext) getJspContext();
    if(_applicationContext==null){
        _applicationContext = RequestContextUtils.getWebApplicationContext(
                pageContext.getRequest(),
                pageContext.getServletContext()
            );
        initCustomBeans();
    }
    return _applicationContext;
}

protected abstract void initCustomBeans();

/**
 * Deprecated for inserting extra logic. Use {@link #doTagWithSpring()} instead.
 */
@Override
@Deprecated
public void doTag() throws JspException, IOException {
    getSpringContext();
    doTagWithSpring();
}


abstract void doTagWithSpring() throws JspException, IOException;
}

And usage:

public class SlotTag extends SpringSuportedTag {

//  @Resource(name="userDetailHolder")
//  not work here
UserDetailHolder userDetail;

private String slotname;

public String getSlotname() {
    return slotname;
}

public void setSlotname(String slotname) {
    this.slotname = slotname;
}

@Override
void doTagWithSpring() throws JspException, IOException {
    PageContext pageContext = (PageContext) getJspContext();
    String userDetailCode = pageContext.getAttribute(InitWidgetUserTag.KAY_USERDETAIL,  PageContext.PAGE_SCOPE).toString();
    userDetail.init(userDetailCode);
    String pageID = pageContext.getAttribute(InitWidgetUserTag.KAY_PAGEID,  PageContext.PAGE_SCOPE).toString();

    getJspContext().getOut().println("<b>slot for user:"+userDetail.getUserId()+"</b>");
}

@Override
protected void initCustomBeans() {
    userDetail = (UserDetailHolder) getSpringContext().getBean("userDetailHolder");

}
}

It's work. But than i found this: Spring supported Tag Libraries. Truth in my progect I still use own solution.

Upvotes: 0

mindas
mindas

Reputation: 26713

What you could do is create a static method like this:

public static void autowireAllFor(Object target) {
    AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
    bpp.setBeanFactory(...yourBeanFactory...);
    bpp.processInjection(target);
}

and then for your tag you could do

public class YourTag extends TagSupport {

   @Autowired
   private SomeBean someBean;

   public YourTag() {
      YourHelperClass.autowireAllFor(this);
   }
}

The obvious disadvantage of this approach is that you have to do this for every constructor, but as TagSupport only has one, it should not be a problem. You can go even one step further and create a helper superclass which always guarantees autowiring:

public class SpringTagSupport extends TagSupport {
   public SpringTagSupport() {
      super();
      YourHelperClass.autowireAllFor(this);
   }
}

The rest is as easy as extending your classes from SpringTagSupport.

Upvotes: 0

Steinway Wu
Steinway Wu

Reputation: 1308

Have a try by utilizing RequestContextAwareTag. It will offer you methods to obtain RequestContext and then WebApplicaitonContext. Have a look at here.

Upvotes: 16

Kai Moritz
Kai Moritz

Reputation: 621

Annotate your Tag-Implementation with @Configurable and add <context:component-scan base-package="your.webapp"> to your Spring-Configuration.

Upvotes: 1

DwB
DwB

Reputation: 38300

Check out these spring packages in the spring reference docs and in the spring source:

  • org.springframework.web.servlet.tags
  • org.springframework.web.servlet.tags.form
  • If nothing else, those will show you how the spring developers wrote the spring tags.

    Upvotes: 0

    skaffman
    skaffman

    Reputation: 403481

    JSP tag objects are not managed by Spring, they are managed by the servlet container. As a result, you cannot autowire stuff into your tags.

    If you need to get hold of beans from the spring appcontext, then your Spring MVC controller needs to set the bean as a request attribute (using request.setAttribute()), so that the tag object can get hold of it.

    Upvotes: 5

    Related Questions