[Logo] JForum - Powering Communities
  [Search] 搜尋   [Recent Topics] 最新主題   [Hottest Topics] 熱門主題   [Top Downloads] 熱門下載   [Members] 會員列表   [Groups] 回首頁 
[Moderation Log] 管理日誌   [Register] 會員註冊 /  [Login] 登入 


JForum 2.5.0 released, download it from here.
Making post from another tomcat application  RSS feed
討論區首頁 » Integration Forum
發表人 內容
jforumrookie


註冊時間: 2011/9/30
文章: 5
離線
Hi,

Does anyone know how I can make a post from another webapp application? We have an existing web application that when a user submit a form, we would like it to make a new topic on the jforum. I have tried following the saveMessage method in InstallAction class and have successfully added the post into the database, but somehow I don't see the new post in the jforum.

Any help or suggestion would be appreciated.

Thanks.
andowson


註冊時間: 2011/6/30
文章: 188
離線
You can use Apache HttpComponents HttpClient to do this. However, JForum needs to have a new API postApi to be called by your application.

The scenario is as follows:
[Your AP] ---HTTP POST--->[JForum postApi]

Your AP makes an HTTP POST to the JForum postApi URL with 5 parameters:
1. api_key: used as a trust key between Your AP and JForum
2. email: poster's email address (should be a user of JForum first)
3. forum_id: the target forum's id
4. subject: subject of the post
5. message: content of the post

For security, you need to add an api_key into the jforum_api table. (api_validity should be a longer future date)
insert into jforum_api(api_key, api_validity) values('yourAp', '2012/12/22');


The postApi pattern looks like the following:
http://localhsot:8080/jforum/postApi/insert/yourAp/somebody@yourcompany.com/1.page

You need to add this pattern into jforum's /WEB-INF/config/urlPattern.properties
# postApi
postApi.insert.3 = api_key, email, forum_id


Finally, I have added a new API in JForum 2.3.2 to help this need. I add this into jforum's /WEB-INF/config/modulesMapping.properties
postApi = net.jforum.api.rest.PostREST


The PostREST.java is as follows:

/*
 * Copyright (c) JForum Team
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, 
 * with or without modification, are permitted provided 
 * that the following conditions are met:
 * 
 * 1) Redistributions of source code must retain the above 
 * copyright notice, this list of conditions and the 
 * following disclaimer.
 * 2) Redistributions in binary form must reproduce the 
 * above copyright notice, this list of conditions and 
 * the following disclaimer in the documentation and/or 
 * other materials provided with the distribution.
 * 3) Neither the name of "Rafael Steil" nor 
 * the names of its contributors may be used to endorse 
 * or promote products derived from this software without 
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
 * IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
 * 
 * Created on 01/10/2011 14:32:22
 * The JForum Project
 * http://www.jforum.net
 */
package net.jforum.api.rest;

import java.util.Date;

import net.jforum.Command;
import net.jforum.JForumExecutionContext;
import net.jforum.SessionFacade;
import net.jforum.context.RequestContext;
import net.jforum.context.ResponseContext;
import net.jforum.dao.DataAccessDriver;
import net.jforum.dao.UserDAO;
import net.jforum.entities.Post;
import net.jforum.entities.Topic;
import net.jforum.entities.User;
import net.jforum.entities.UserSession;
import net.jforum.exceptions.APIException;
import net.jforum.util.I18n;
import net.jforum.util.preferences.ConfigKeys;
import net.jforum.util.preferences.SystemGlobals;
import net.jforum.util.preferences.TemplateKeys;
import net.jforum.view.forum.PostAction;

import org.apache.commons.lang3.StringUtils;

import freemarker.template.SimpleHash;
import freemarker.template.Template;

/**
 * @author Andowson Chang
 *
 */
public class PostREST extends Command {

	/* (non-Javadoc)
	 * @see net.jforum.Command#list()
	 */
	@Override
	public void list() {
		try {
			this.authenticate();
			// do nothing here
			// TODO: add implementation
		}
		catch (Exception e) {
			this.setTemplateName(TemplateKeys.API_ERROR);
			this.context.put("exception", e);
		}
	}

	/**
	 * Creates a new post.
	 * Required parameters are "email", "forum_id", "subject" and "message".
	 */
	public void insert()
	{
		try {
			this.authenticate();
			
			final String email = this.requiredRequestParameter("email");
			final String forumId = this.requiredRequestParameter("forum_id");
			final String subject = this.requiredRequestParameter("subject");
			final String message = this.requiredRequestParameter("message");
					
			final UserDAO dao = DataAccessDriver.getInstance().newUserDAO();			
			User user = dao.findByEmail(email);
			// If user's email not exists, use anonymous instead
			if (user == null) {
				user = new User();
				user.setId(SystemGlobals.getIntValue(ConfigKeys.ANONYMOUS_USER_ID));
				user.setUsername(I18n.getMessage("Guest"));
			}
			// OK, time to insert the post
			final UserSession userSession = SessionFacade.getUserSession();
			userSession.setUserId(user.getId());
			userSession.setUsername(user.getUsername());
			String sessionId = userSession.getSessionId(); 
			userSession.setStartTime(new Date(System.currentTimeMillis()));
			SessionFacade.makeLogged();

			SessionFacade.removeAttribute(ConfigKeys.LAST_POST_TIME);
			SessionFacade.setAttribute(ConfigKeys.REQUEST_IGNORE_CAPTCHA, "1");

			final Post post = new Post();
			post.setForumId(Integer.valueOf(forumId));
			post.setSubject(subject);
			post.setText(message);				
			this.insertMessage(user, post);
			SessionFacade.makeUnlogged();
			SessionFacade.remove(sessionId);			
		}
		catch (Exception e) {
			this.setTemplateName(TemplateKeys.API_ERROR);
			this.context.put("exception", e);
		}
	}
	
	/**
	 * Calls {@link PostAction#insertSave()}
	 * @param post the post
	 * @param user the user who's doing the post
	 */
	private void insertMessage(final User user, final Post post)
	{
		this.addDataToRequest(user, post);
		
		final PostAction postAction = new PostAction(JForumExecutionContext.getRequest(), new SimpleHash());
		postAction.insertSave();
	}
	
	/**
	 * Extracts information from a mail message and adds it to the request context
	 * @param post the post
	 * @param user the user who's doing the post
	 */
	private void addDataToRequest(final User user, final Post post)
	{
		final RequestContext request = JForumExecutionContext.getRequest(); 

		request.addParameter("topic_type", Integer.toString(Topic.TYPE_NORMAL));
		request.addParameter("quick", "1");
		
		final int topicId = post.getTopicId();
		if (topicId > 0) {
			request.addParameter("topic_id", Integer.toString(topicId));
		}
		
		if (!user.isBbCodeEnabled()) {
			request.addParameter("disable_bbcode", "on");
		}
		
		if (!user.isSmiliesEnabled()) {
			request.addParameter("disable_smilies", "on");
		}
		
		if (!user.isHtmlEnabled()) {
			request.addParameter("disable_html", "on");
		}
	}	
	
	/**
	 * Retrieves a parameter from the request and ensures it exists
	 * @param paramName the parameter name to retrieve its value
	 * @return the parameter value
	 * @throws APIException if the parameter is not found or its value is empty
	 */
	private String requiredRequestParameter(final String paramName)
	{
		final String value = this.request.getParameter(paramName);
		
		if (StringUtils.isBlank(value)) {
			throw new APIException("The parameter '" + paramName + "' was not found");
		}
		
		return value;
	}

	/**
	 * Tries to authenticate the user accessing the API
	 * @throws APIException if the authentication fails
	 */
	private void authenticate()
	{
		final String apiKey = this.requiredRequestParameter("api_key");
		
		final RESTAuthentication auth = new RESTAuthentication();
		
		if (!auth.validateApiKey(apiKey)) {
			throw new APIException("The provided API authentication information is not valid");
		}
	}
	
	public Template process(final RequestContext request, final ResponseContext response, final SimpleHash context)
	{
		JForumExecutionContext.setContentType("text/xml");
		return super.process(request, response, context);
	}
}


And you can use the following example to do the test:

package com.andowson.integration;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

/**
 * A example that demonstrates how HttpClient APIs can be used to perform
 * adding a post outside JForum.
 */
public class AddPostOutsideJForum {

    public static void main(String[] args) throws Exception {

        DefaultHttpClient httpclient = new DefaultHttpClient();
        try {
        	String apiKey = "yourAp";
        	String email = "somebody@yourcompany.com";
        	int forumId = 1;
        	String subject = "postApi test";
        	String message = "This is a test post outside JForum.\nBBCode test :)";
            String baseURL = "http://localhost:8080/jforum/";
            
        	HttpPost httppost = new HttpPost(baseURL + "postApi/insert/" +
                    apiKey + "/" + email + "/" + forumId + ".page");        	
        	
        	List <NameValuePair> nvps = new ArrayList <NameValuePair>();
            nvps.add(new BasicNameValuePair("subject", subject));
            nvps.add(new BasicNameValuePair("message", message));

            httppost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));

            System.out.println("executing request " + httppost.getURI());
            
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            System.out.println("status: " + response.getStatusLine());
            System.out.println(EntityUtils.toString(entity));           
        } finally {
            // When HttpClient instance is no longer needed,
            // shut down the connection manager to ensure
            // immediate deallocation of all system resources
            httpclient.getConnectionManager().shutdown();
        }
    }
}
 檔案名稱 AddPostOutsideJForum.java [Disk] 下載
 描述 example for add post outside JForum
 檔案大小 2 Kbytes
 下載次數:  15559 次

 檔案名稱 PostREST.java [Disk] 下載
 描述 PostREST.java
 檔案大小 7 Kbytes
 下載次數:  15740 次

jforumrookie


註冊時間: 2011/9/30
文章: 5
離線
Thanks! I will give this a try.
jforumrookie


註冊時間: 2011/9/30
文章: 5
離線
Thanks andowson for this added feature. It works beautifully. One more request if possible. Is it possible for the PostREST to return the post id or a link to the post after the insert?

I tried to mod it like UserREST, but no success. I keep getting a response of 302 Move Temporary.

Thanks,
andowson


註冊時間: 2011/6/30
文章: 188
離線
I've tried to do the same thing as you said during the implementation. And keep getting a response of 302 Move Temporary, too.
So finally I decide to make it works as only support adding a post outside but no post id returned.

You may tried to modify the PostAction.java's insertSave() method's return type from void to int and get the postId returned.
jforumrookie


註冊時間: 2011/9/30
文章: 5
離線
Thanks. I'll give it a try.
jforumrookie


註冊時間: 2011/9/30
文章: 5
離線
Thanks andowson. After some debugging, it looks like PostAction.insertSave is redirecting the path. So I didn't change any of its code. What I ended up doing was in the PostREST, I retrieve the post link from JForumExecutionContext.getRedirectTo() and then set it to null with JForumExecutionContext.setRedirect(null). That seem to do the trick.

Here's a sample snipplet of my modified PostREST.java
public void insert() 
{
   ...
   final Post post = new Post();
   post.setForumId(Integer.valueOf(forumId));
   post.setSubject(subject);
   post.setText(message);
   this.insertMessage(user, post);

   // new start
   String postLink = JForumExecutionContext.getRedirectTo();
   JForumExecutionContext.setRedirect(null);
   this.setTemplateName(TemplateKeys.API_POST_INSERT);
   this.context.put("postLink", postLink);
   // new end

   SessionFacade.makeUnlogged();
   SessionFacade.remove(sessionId);
   ...
}

Thanks!
andowson


註冊時間: 2011/6/30
文章: 188
離線
Nice! I'll add this to the next release.
Thank you, jforumrookie.
 
討論區首頁 » Integration Forum
前往:   
行動版
Powered by JForum 2.5.0 © 2018 JForum Team • Maintained by Andowson Chang and Ulf Dittmer