org.rhq.coregui.server.gwt.AbstractGWTServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.rhq.coregui.server.gwt.AbstractGWTServiceImpl.java

Source

/*
 * RHQ Management Platform
 * Copyright (C) 2005-2010 Red Hat, Inc.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation version 2 of the License.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package org.rhq.coregui.server.gwt;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.gwt.user.server.rpc.RPCRequest;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.util.HibernatePerformanceMonitor;
import org.rhq.enterprise.server.util.LookupUtil;

/**
 * @author Greg Hinkle
 * @author Joseph Marques
 */
public abstract class AbstractGWTServiceImpl extends RemoteServiceServlet {

    private static final long serialVersionUID = 1L;
    private Log log = LogFactory.getLog(this.getClass());

    private ThreadLocal<Subject> sessionSubject = new ThreadLocal<Subject>();
    private ThreadLocal<String> rpcMethod = new ThreadLocal<String>();

    protected Subject getSessionSubject() {
        return sessionSubject.get();
    }

    protected Log getLog() {
        return log;
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (log.isTraceEnabled()) {
            printHeaders(req);
        }

        boolean continueProcessing = true;
        String sid = req.getHeader("RHQ_Session");
        if (sid != null) {
            SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
            try {
                Subject subject = subjectManager.getSubjectBySessionId(Integer.parseInt(sid));
                sessionSubject.set(subject);
            } catch (Exception e) {
                log.trace("Failed to validate request: sessionId was '" + sid + "', requestURL="
                        + req.getRequestURL());
                continueProcessing = false;
            }
        } else {
            log.debug("Failed to validate request: sessionId missing, requestURL=" + req.getRequestURL());
            continueProcessing = false;
        }

        if (continueProcessing) {
            // TODO: only execute this if the session lookup was successful, otherwise fail in some deterministic fashion
            //       alter callback handlers to capture expected failure and retry (at least once)
            //      to add resilience to gwt service calls
            long id = HibernatePerformanceMonitor.get().start();
            super.service(req, resp);
            HibernatePerformanceMonitor.get().stop(id, "GWT:" + rpcMethod.get());
        }
    }

    @Override
    protected void onAfterRequestDeserialized(RPCRequest rpcRequest) {
        super.onAfterRequestDeserialized(rpcRequest);

        Method rpcMethod = rpcRequest.getMethod();
        String className = rpcMethod.getDeclaringClass().getSimpleName();
        String methodName = rpcMethod.getName();

        this.rpcMethod.set(className + "." + methodName);
    }

    /**
     * Our GWT Service implementations should call this whenever it needs to send an exception to the GWT client.
     * @param t the server side exception that needs to be thrown
     * @returns a RuntimeException that is the real exception that should be thrown to the GWT client
     */
    protected RuntimeException getExceptionToThrowToClient(Throwable t) throws RuntimeException {
        return getExceptionToThrowToClient(t, null);
    }

    /**
     * Our GWT Service implementations should call this whenever it needs to send an exception to the GWT client.
     * @param t the server side exception that needs to be thrown
     * @param message an extra message to put in the returned exception
     * @returns a RuntimeException that is the real exception that should be thrown to the GWT client
     */
    protected RuntimeException getExceptionToThrowToClient(Throwable t, String message) throws RuntimeException {
        // this id is so the user can correlate this exception in the server log with the client message in the browser
        StringBuilder id = new StringBuilder("[");
        id.append(System.currentTimeMillis());
        if (message != null) {
            id.append(" ").append(message);
        }
        id.append("] ");

        // log the exception server-side
        log.warn("Sending exception to client: " + id.toString(), t);

        // cannot assume gwt client has our exception classes, only send the messages in a generic runtime exception
        return new RuntimeException(id.toString() + ThrowableUtil.getAllMessages(t));
    }

    @SuppressWarnings("unchecked")
    private void printHeaders(HttpServletRequest req) {
        // TODO: figure out why SESSION_NAME header and other GWT-specific headers are missing occasionally
        //       seems to only happen on polling for recent alerts when there is no user activity for a few minutes
        Enumeration<String> headerNames = req.getHeaderNames();
        log.trace(req.getRequestURL().toString());
        while (headerNames.hasMoreElements()) {
            log.trace("   " + headerNames.nextElement());
        }
    }
}