0

Run a class for every server request?

asked 2012-12-19 21:15:43 +0800

davout gravatar image davout
1435 3 18

Is there a way inside ZK to have a class run for each request from the client to the server?

For a multi tenant application I'm using a ThreadLocal to store a key to identify what data source to access. I can't think of a way of storing a thread local somewhere and have it reloaded for every request.

delete flag offensive retag edit

4 Replies

Sort by » oldest newest

answered 2012-12-20 20:59:30 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

do you work with hibernate?

link publish delete flag offensive edit

answered 2012-12-21 07:02:25 +0800

davout gravatar image davout
1435 3 18

Yes - this part of a problem of making my web app multi tenant.

link publish delete flag offensive edit

answered 2012-12-21 08:30:21 +0800

gekkio gravatar image gekkio flag of Finland
899 1
http://gekkio.fi/blog

A simple Servlet filter should work fine, or alternatively thet ExecutionInit/ExecutionCleanup -mechanism if you need access to ZK-specific stuff.

link publish delete flag offensive edit

answered 2012-12-21 10:05:31 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

updated 2012-12-21 10:12:31 +0800

I remember that i have searched a long time for a hibernate inBuild mechanism for to do that and found a simple but working idea in a blog.

I can adapt all three kinds of multi-tenancy with it.

1. All tenants data in a single table with a discriminator field.
2. All tenants data in separated tables (schemas)
3. All tenants data in separated databases.

Try this:

/**
 * Copyright (C) 2010 - 2013 Forsthaus IT Consulting GbR.
 * 
 * This file is part of openTruuls™. http://www.opentruuls.org/
 *
 * openTruuls™ community edition is free software: 
 * you can redistribute it and/or modify it under the terms of the 
 * GNU Lesser General Public License as published by the Free Software 
 * Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses></http:>.
 *    
 * If you need a commercial license please write us under [email protected]
 */
package org.opentruuls.backend.data.util;

import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.hibernate.EmptyInterceptor;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

/**
 * EN: Hibernate Interceptor. The prepared SQL Statement will be modified for
 * the tenants table schemata name used by the tenant before Hibernate is
 * executing the query.<br>
 * <br>
 * DE: Hibernate Interceptor. Hier wird das vorbereitete SQL Statement mit dem
 * zum Mandanten gehoerigen Tabellen Schema Namen ergaenzt bevor Hibernate es
 * ausfuehrt. D.h. der default Tabellen SchemaName 'public' wird mit dem jeweils
 * zum Mandanten gehoerigen Namen ersetzt. Der Name 'public' ist also geschuetzt
 * und sollte keinesfalls weder in einem TabellenNamen oder einem FeldNamen
 * vorkommen<br>
 * <br>
 * Besser: '"PUBLIC"."' = '"4711"."' | SELECT * FROM "PUBLIC"."MYTABLE" <br>
 * <br>
 * TODO Es ist natuerlich sicherer den Tabellen SchemaNamen extern zu setzen als
 * durch eine String Manipulation im abzusetzenden SQL-Statement. Fuer
 * PostgreSQL hiesse dass, den 'search_path' zu setzen:<br>
 * // String sPath = "SET search_path TO " + schemaName; <br>
 * 
 * @author Stephan Gerth
 */
public class FHHibernateInterceptor extends EmptyInterceptor {

	private static final long serialVersionUID = 1L;

	@Override
	public String onPrepareStatement(String sql) {

		String preparedStatement = super.onPrepareStatement(sql);
		String schemaName = getSchemaNameFromSessionContext();

		if (StringUtils.isNotEmpty(schemaName)) {
			preparedStatement = preparedStatement.replaceAll("public.", schemaName + ".");
		}

		return preparedStatement;
	}

	/**
	 * EN: Gets the tables schema name from the Users SessionContext.<br>
	 * 
	 * DE: Gibt den Tabellen Schema Namen aus dem User Session Kontext zurueck.<br>
	 * 
	 * @return table schema name / Tabellen Schema Name
	 * @see de.forsthaus.policy.model.PolicyManager
	 */
	private String getSchemaNameFromSessionContext() {

		RequestAttributes atr = RequestContextHolder.currentRequestAttributes();
		HttpSession ses = (HttpSession) atr.getSessionMutex();
		String res = (String) ses.getAttribute("SchemaName");
		String result = StringUtils.trim(res);

		// System.out.println("----------> SessionID :" + atr.getSessionId());

		return result;
	}

}


FHSessionUtil.java
Sets the table schema name after a login from the tenant user

   . . .

	/**
	 * EN: Sets the TableSchemaName Attribute in the user's session.<br>
	 * DE: Setzt das TableSchemaName Attribut in der User Session.<br>
	 * 
	 * @param schemaName
	 *            the table schema name / Der Tabellen Schema Name
	 */
	public static void setTablesSchemaName(String schemaName) {
		getSession().setAttribute("SchemaName", schemaName);
	}

    . . .


best
Stephan

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2012-12-19 21:15:43 +0800

Seen: 74 times

Last updated: Dec 21 '12

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More