Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Refresh a Page after editing its Body

Bart Kerfeld July 6, 2015

Recently I have build a plugin which automatically adds links to a page based on the titles of pages in the same space. For example, if I have a page called "Dog" in a space and I make new page with text "My Dog is awesome!" it will automatically add a link to the page dog. The basic source code looks something like this without getting too deep into the details. (let me know if you want them though)

public class AnnotatedListener implements DisposableBean  {
    private static final Logger log = LoggerFactory.getLogger(AnnotatedListener.class);
    
    protected EventPublisher eventPublisher;
    protected PageManager pageManager;
    
    public AnnotatedListener(EventPublisher eventPublisher, PageManager pageManager) {
        linkMarkupForPerfectMatch = "<ac:link><ri:page ri:content-title=\"%s\"/></ac:link>";
        linkMarkupForCloseMatch = "<ac:link><ri:page ri:content-title=\"%s\"/><ac:plain-text-link-body><![CDATA[%s]]></ac:plain-text-link-body></ac:link>";
        this.eventPublisher = eventPublisher;
        this.pageManager = pageManager;
        eventPublisher.register(this);
    }
    
    @EventListener
    public void pageCreateEvent(PageCreateEvent event) {
        processEvent(event.getPage());
    }
    
    @EventListener
    public void pageUpdateEvent(PageUpdateEvent event) {
        processEvent(event.getPage());
    }
    
	@EventListener
    public void pageViewEvent(PageViewEvent event) {
        processEvent(event.getPage());    
    }
    
    @Override
    public void destroy() throws Exception {
        eventPublisher.unregister(this);
    }    
    
    /*
     * Input: a confluence page
     * Description: This method does the following things
     *   1) it finds all the pages in a space which are current
     *   2) it grabs all of these page titles (ignoring a few blacklisted items)
     *      and it stores them in a list.
     *   3) it sorts this list in order from longest to shortest title. This
     *      solves a problem where one title is a substring of another and the
     *      shorter title gets linked when the larger one could have been.
     *   4) it creates a Regex pattern to find all text between <> and <a ... </a>
     *   5) it calls the parseExact and parseClose methods to add links to the body
     *   6) it updates the page body
     */
    private void processEvent(Page page) {
        // clear variables
        startingBody = "";
        afterExact = "";
        afterClose = "";
        
        Space space = page.getSpace();

        List<Page> pages = pageManager.getPages(space, true); // boolean parameter is currentOnly
        
        ArrayList<String> pageTitles = new ArrayList<String>();        
        for (Page _page : pages) {
            String title = _page.getTitle();
            if (title.startsWith("_") == false) { 
                pageTitles.add(title);
            }
        }
    
        String currentTitle = page.getTitle();
        pageTitles.remove(currentTitle); // don't link to same page
        
        Collections.sort(pageTitles, new Comparator<String>() {
            public int compare(String o1, String o2) {
                if(o1.length() > o2.length())
                    return -1;
                else if(o2.length() > o1.length())
                    return 1;
                else
                    return 0;
            }
        });
        
        String body = page.getBodyAsString();
        String original = body;
        
        Pattern pattern = Pattern.compile("(<a\\s(.*?)</a>)|(<.+?>)");
        try {
            startingBody = body;
            body = parseExact(body, pageTitles, pattern);
            afterExact = body;
            body = parseClose(body, pageTitles, pattern);
            afterClose = body;
            page.setBodyAsString(body);
            if (body.equals(original) == false) {
                log.info("INFO: Automatic Linker added links to Page:" + currentTitle + " successfully.");
            }
        } catch (Exception ex) {
            log.warn("WARN: Exception occureed in Automatic Linker on Page: " + currentTitle
                    + "\r\nException: " + ex.toString() + "\r\nstartingBody: " + startingBody
                    + "\r\nafterExact: " + afterExact + "\r\n afterClose: " + afterClose);
        }
            
    }

As you can see, the process is run every time a page is created, updated, or simply viewed. Now finally, to the question. This process does indeed work on PageViewEvents, but it requires the user to refresh before seeing the effect. I was wondering if there was some way I could automatically refresh the page for the user after the process is complete. Any ideas?

Thanks for the help.

1 answer

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

1 vote
Answer accepted
xpauls
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 6, 2015

You can use servlets to send redirect. You can use this refresh method to do that.

public void refresh() {
        HttpServletRequest request = ServletActionContext.getRequest();
        String requestUrl = request.getRequestURI();
        String queryString = request.getQueryString();
        if (queryString != null)
            requestUrl = requestUrl + "?" + queryString;
   		
        try {
            ServletActionContext.getResponse().sendRedirect(requestUrl);
        } catch (IOException e) {
            log.error("Unable to redirect");
            //log.error(ExceptionUtils.getFullStackTrace(e));
        }
    }

But beware, use this refresh only when processEvent is successful. Otherwise it will go in the loop where it will refresh the page that has been refreshed and so on.

Bart Kerfeld July 7, 2015

This worked for me. Thank you very much!

TAGS
AUG Leaders

Atlassian Community Events