SOLR-215 -- removing static references to "instanceDir" -- this will let each core have its own instanceDir and ClassLoader

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@573946 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Ryan McKinley 2007-09-09 04:34:44 +00:00
parent ec60f7a3ca
commit 2e1941b207
18 changed files with 110 additions and 118 deletions

View File

@ -268,7 +268,7 @@ public class Config {
private static final String base = "org.apache" + "." + project;
private static final String[] packages = {"","analysis.","schema.","handler.","search.","update.","core.","request.","update.processor.","util."};
public static Class findClass(String cname, String... subpackages) {
public Class findClass(String cname, String... subpackages) {
ClassLoader loader = getClassLoader();
if (subpackages.length==0) subpackages = packages;
@ -294,16 +294,24 @@ public class Config {
}
}
public static Object newInstance(String cname, String... subpackages) {
public Object newInstance(String cname, String... subpackages) {
Class clazz = findClass(cname,subpackages);
if( clazz == null ) {
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,
"Can not find class: "+cname + " in " + getClassLoader(), false);
}
try {
return clazz.newInstance();
} catch (Exception e) {
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Error instantiating class " + clazz, e, false);
}
catch (Exception e) {
e.printStackTrace();
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,
"Error instantiating class: '" + clazz.getName()+"'", e, false );
}
}
private static String instanceDir; // solr home directory
private String instanceDir; // solr home directory
private static String normalizeDir(String path) {
if (path==null) return null;
if ( !(path.endsWith("/") || path.endsWith("\\")) ) {
@ -312,14 +320,14 @@ public class Config {
return path;
}
public static void setInstanceDir(String dir) {
public void setInstanceDir(String dir) {
instanceDir = normalizeDir(dir);
classLoader = null;
log.info("Solr home set to '" + instanceDir + "'");
}
public static String getInstanceDir() {
if ( ! isInstanceDirInitialized() ) {
public String getInstanceDir() {
if ( !isInstanceDirInitialized() ) {
String home = null;
// Try JNDI
try {
@ -355,7 +363,7 @@ public class Config {
return instanceDir;
}
public static boolean isInstanceDirInitialized() {
public boolean isInstanceDirInitialized() {
return instanceDir != null;
}
@ -372,7 +380,7 @@ public class Config {
* found in the "lib/" directory in the "Solr Home" directory.
* <p>
*/
static ClassLoader getClassLoader() {
ClassLoader getClassLoader() {
if (null == classLoader) {
// NB5.5/win32/1.5_10: need to go thru local var or classLoader is not set!
ClassLoader loader = Thread.currentThread().getContextClassLoader();

View File

@ -37,7 +37,6 @@ class QuerySenderListener extends AbstractSolrEventListener {
@Override
public void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher) {
final SolrIndexSearcher searcher = newSearcher;
SolrCore core = SolrCore.getSolrCore();
log.info("QuerySenderListener sending requests to " + newSearcher);
for (NamedList nlst : (List<NamedList>)args.get("queries")) {
try {

View File

@ -126,14 +126,14 @@ final class RequestHandlers {
*
* Handlers will be registered and initialized in the order they appear in solrconfig.xml
*/
void initHandlersFromConfig( Config config )
void initHandlersFromConfig( final Config config )
{
final RequestHandlers handlers = this;
AbstractPluginLoader<SolrRequestHandler> loader =
new AbstractPluginLoader<SolrRequestHandler>( "[solrconfig.xml] requestHandler", true, true )
{
@Override
protected SolrRequestHandler create( SolrCore core, String name, String className, Node node ) throws Exception
protected SolrRequestHandler create( Config config, String name, String className, Node node ) throws Exception
{
String startup = DOMUtil.getAttr( node, "startup" );
if( startup != null ) {
@ -146,7 +146,7 @@ final class RequestHandlers {
throw new Exception( "Unknown startup value: '"+startup+"' for: "+className );
}
}
return super.create( core, name, className, node );
return super.create( config, name, className, node );
}
@Override
@ -163,7 +163,7 @@ final class RequestHandlers {
NodeList nodes = (NodeList)config.evaluate("requestHandler", XPathConstants.NODESET);
// Load the handlers and get the default one
SolrRequestHandler defaultHandler = loader.load( core, nodes );
SolrRequestHandler defaultHandler = loader.load( config, nodes );
if( defaultHandler == null ) {
defaultHandler = get(RequestHandlers.DEFAULT_HANDLER_NAME);
if( defaultHandler == null ) {

View File

@ -21,7 +21,6 @@ import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -34,7 +33,6 @@ import java.util.logging.Logger;
import javax.xml.xpath.XPathConstants;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
@ -57,7 +55,6 @@ import org.apache.solr.request.XMLResponseWriter;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.update.DirectUpdateHandler;
import org.apache.solr.update.SolrIndexConfig;
import org.apache.solr.update.SolrIndexWriter;
import org.apache.solr.update.UpdateHandler;
import org.apache.solr.update.processor.ChainedUpdateProcessorFactory;
@ -134,7 +131,7 @@ public final class SolrCore {
for (int i=0; i<nodes.getLength(); i++) {
Node node = nodes.item(i);
String className = DOMUtil.getAttr(node,"class");
SolrEventListener listener = (SolrEventListener)Config.newInstance(className);
SolrEventListener listener = (SolrEventListener)solrConfig.newInstance(className);
listener.init(DOMUtil.childNodesToNamedList(node));
lst.add(listener);
log.info("added SolrEventListener: " + listener);
@ -209,6 +206,7 @@ public final class SolrCore {
clazz = solrConfig.findClass(className);
if (cast != null && !cast.isAssignableFrom(clazz))
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,"Error Instantiating "+msg+", "+className+ " is not a " +cast.getName());
java.lang.reflect.Constructor cons = clazz.getConstructor(new Class[]{SolrCore.class});
return (T) cons.newInstance(new Object[]{this});
} catch(NoSuchMethodException xnomethod) {
@ -235,9 +233,10 @@ public final class SolrCore {
// The registry of known cores
private static Map<String, SolrCore> cores = new HashMap();
private static Map<String, SolrCore> cores = new HashMap<String, SolrCore>();
/** Alias for SolrCore.getSolrCore(null). */
@Deprecated
public static SolrCore getSolrCore() {
return getSolrCore(null);
}
@ -328,7 +327,7 @@ public final class SolrCore {
else
this.schema = schema;
this.dataDir = dataDir;
this.dataDir = dataDir;
if (name == null)
this.index_path = dataDir + "/index";
else
@ -339,33 +338,33 @@ public final class SolrCore {
booleanQueryMaxClauseCount();
this.maxWarmingSearchers = solrConfig.getInt("query/maxWarmingSearchers",Integer.MAX_VALUE);
parseListeners();
parseListeners();
initIndex();
initWriters();
// Processors initialized before the handlers
updateProcessors = loadUpdateProcessors();
reqHandlers = new RequestHandlers(this);
reqHandlers.initHandlersFromConfig( solrConfig );
initIndex();
initWriters();
// Processors initialized before the handlers
updateProcessors = loadUpdateProcessors();
reqHandlers = new RequestHandlers(this);
reqHandlers.initHandlersFromConfig( solrConfig );
// TODO? could select the highlighter implementation
highlighter = new SolrHighlighter();
// TODO? could select the highlighter implementation
highlighter = new SolrHighlighter();
highlighter.initalize( solrConfig );
try {
// Open the searcher *before* the handler so we don't end up opening
// one in the middle.
getSearcher(false,false,null);
try {
// Open the searcher *before* the handler so we don't end up opening
// one in the middle.
getSearcher(false,false,null);
updateHandler = createUpdateHandler(
solrConfig.get("updateHandler/@class", DirectUpdateHandler.class.getName())
);
updateHandler = createUpdateHandler(
solrConfig.get("updateHandler/@class", DirectUpdateHandler.class.getName())
);
} catch (IOException e) {
throw new RuntimeException(e);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
// register this core
synchronized(cores) {
SolrCore previous = cores.get(name);
@ -383,12 +382,13 @@ public final class SolrCore {
final Map<String,UpdateRequestProcessorFactory> map = new HashMap<String, UpdateRequestProcessorFactory>();
// If this is a more general use-case, this could be a regular type
final SolrCore thiscore = this;
AbstractPluginLoader<UpdateRequestProcessorFactory> loader
= new AbstractPluginLoader<UpdateRequestProcessorFactory>( "updateRequestProcessor" ) {
@Override
protected void init(UpdateRequestProcessorFactory plugin, Node node) throws Exception {
plugin.init( node );
plugin.init( thiscore, node );
}
@Override
@ -398,10 +398,10 @@ public final class SolrCore {
};
NodeList nodes = (NodeList)solrConfig.evaluate("updateRequestProcessor/factory", XPathConstants.NODESET);
UpdateRequestProcessorFactory def = loader.load( nodes );
UpdateRequestProcessorFactory def = loader.load( solrConfig, nodes );
if( def == null ) {
def = new ChainedUpdateProcessorFactory(); // the default
def.init( null );
def.init( thiscore, null );
}
map.put( null, def );
map.put( "", def );
@ -956,7 +956,7 @@ public final class SolrCore {
NamedListPluginLoader<QueryResponseWriter> loader =
new NamedListPluginLoader<QueryResponseWriter>( "[solrconfig.xml] "+xpath, responseWriters );
defaultResponseWriter = loader.load( this, nodes );
defaultResponseWriter = loader.load( solrConfig, nodes );
// configure the default response writer; this one should never be null
if (defaultResponseWriter == null) {

View File

@ -88,7 +88,7 @@ public class SystemInfoHandler extends RequestHandlerBase
// Solr Home
SimpleOrderedMap<Object> dirs = new SimpleOrderedMap<Object>();
dirs.add( "instance", new File( Config.getInstanceDir() ).getAbsolutePath() );
dirs.add( "instance", new File( core.getSolrConfig().getInstanceDir() ).getAbsolutePath() );
dirs.add( "data", new File( core.getDataDir() ).getAbsolutePath() );
dirs.add( "index", new File( core.getIndexDir() ).getAbsolutePath() );
info.add( "directory", dirs );

View File

@ -58,6 +58,10 @@ import org.apache.solr.util.SolrPluginUtils;
import org.apache.solr.util.plugin.NamedListPluginLoader;
import org.w3c.dom.NodeList;
/**
*
* @since solr 1.3
*/
public class SolrHighlighter
{
public static Logger log = Logger.getLogger(SolrHighlighter.class.getName());
@ -70,7 +74,7 @@ public class SolrHighlighter
protected final Map<String,SolrFragmenter> fragmenters =
Collections.synchronizedMap( new HashMap<String, SolrFragmenter>() );
public void initalize( Config config )
public void initalize( final Config config )
{
formatters.clear();
fragmenters.clear();
@ -78,7 +82,7 @@ public class SolrHighlighter
// Load the fragmenters
String xpath = "highlighting/fragmenter";
NamedListPluginLoader<SolrFragmenter> fragloader = new NamedListPluginLoader<SolrFragmenter>( xpath, fragmenters );
SolrFragmenter frag = fragloader.load( (NodeList)config.evaluate( xpath, XPathConstants.NODESET ) );
SolrFragmenter frag = fragloader.load( config, (NodeList)config.evaluate( xpath, XPathConstants.NODESET ) );
if( frag == null ) {
frag = new GapFragmenter();
}
@ -88,7 +92,7 @@ public class SolrHighlighter
// Load the formatters
xpath = "highlighting/formatter";
NamedListPluginLoader<SolrFormatter> fmtloader = new NamedListPluginLoader<SolrFormatter>( xpath, formatters );
SolrFormatter fmt = fmtloader.load( (NodeList)config.evaluate( xpath, XPathConstants.NODESET ) );
SolrFormatter fmt = fmtloader.load( config, (NodeList)config.evaluate( xpath, XPathConstants.NODESET ) );
if( fmt == null ) {
fmt = new HtmlFormatter();
}

View File

@ -77,7 +77,7 @@ public final class IndexSchema {
return solrConfig;
}
/**
* Direct acess to the InputStream for the schemaFile used by this instance.
* Direct access to the InputStream for the schemaFile used by this instance.
*
* @see Config#openResource
*/
@ -293,7 +293,7 @@ public final class IndexSchema {
}
private void readSchema(SolrConfig solrConfig) {
private void readSchema(final SolrConfig solrConfig) {
log.info("Reading Solr Schema");
try {
@ -320,9 +320,9 @@ public final class IndexSchema {
AbstractPluginLoader<FieldType> loader = new AbstractPluginLoader<FieldType>( "[schema.xml] fieldType" ) {
@Override
protected FieldType create( SolrCore core, String name, String className, Node node ) throws Exception
protected FieldType create( Config config, String name, String className, Node node ) throws Exception
{
FieldType ft = (FieldType)Config.newInstance(className);
FieldType ft = (FieldType)solrConfig.newInstance(className);
ft.setTypeName(name);
String expression = "./analyzer[@type='query']";
@ -359,7 +359,7 @@ public final class IndexSchema {
String expression = "/schema/types/fieldtype | /schema/types/fieldType";
NodeList nodes = (NodeList) xpath.evaluate(expression, document, XPathConstants.NODESET);
loader.load( nodes );
loader.load( solrConfig, nodes );

View File

@ -25,7 +25,6 @@ import java.util.Map;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.DOMUtil;
import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.Config;
import javax.xml.xpath.XPathConstants;
@ -38,7 +37,7 @@ import javax.xml.xpath.XPathConstants;
*/
public class CacheConfig {
private String nodeName;
private Map args;
private Map<String,String> args;
private String cacheImpl;
private Class clazz;
@ -61,7 +60,7 @@ public class CacheConfig {
if (nodes==null || nodes.getLength()==0) return null;
CacheConfig[] configs = new CacheConfig[nodes.getLength()];
for (int i=0; i<nodes.getLength(); i++) {
configs[i] = getConfig(nodes.item(i));
configs[i] = getConfig(solrConfig, nodes.item(i));
}
return configs;
}
@ -69,11 +68,11 @@ public class CacheConfig {
public static CacheConfig getConfig(SolrConfig solrConfig, String xpath) {
Node node = (Node)solrConfig.getNode(xpath, false);
return getConfig(node);
return getConfig(solrConfig, node);
}
public static CacheConfig getConfig(Node node) {
public static CacheConfig getConfig(SolrConfig solrConfig, Node node) {
if (node==null) return null;
CacheConfig config = new CacheConfig();
config.nodeName = node.getNodeName();
@ -85,9 +84,9 @@ public class CacheConfig {
config.cacheImpl = (String)config.args.get("class");
config.regenImpl = (String)config.args.get("regenerator");
config.clazz = Config.findClass(config.cacheImpl);
config.clazz = solrConfig.findClass(config.cacheImpl);
if (config.regenImpl != null) {
config.regenerator = (CacheRegenerator) Config.newInstance(config.regenImpl);
config.regenerator = (CacheRegenerator) solrConfig.newInstance(config.regenImpl);
}

View File

@ -37,16 +37,10 @@ import org.apache.solr.request.SolrQueryRequest;
/**
* @version $Id$
*/
@Deprecated
public class OldRequestHandler implements SolrRequestHandler {
SolrCore core;
long numRequests;
long numErrors;
public OldRequestHandler(SolrCore core) {
this.core = core;
}
public void init(NamedList args) {
SolrCore.log.log(Level.INFO, "Unused request handler arguments:" + args);

View File

@ -41,21 +41,14 @@ import org.apache.solr.request.SolrQueryResponse;
/**
* @version $Id$
*/
@Deprecated
public class TestRequestHandler implements SolrRequestHandler {
private static Logger log = Logger.getLogger(SolrIndexSearcher.class.getName());
SolrCore core;
public TestRequestHandler(SolrCore core) {
this.core = core;
}
public void init(NamedList args) {
SolrCore.log.log(Level.INFO, "Unused request handler arguments:" + args);
}
// use test instead of assert since asserts may be turned off
public void test(boolean condition) {
try {

View File

@ -25,6 +25,7 @@ import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.apache.solr.common.SolrException;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrQueryResponse;
import org.apache.solr.util.plugin.AbstractPluginLoader;
@ -54,7 +55,7 @@ public class ChainedUpdateProcessorFactory extends UpdateRequestProcessorFactory
protected UpdateRequestProcessorFactory[] factory;
@Override
public void init( Node node ) {
public void init( final SolrCore core, final Node node ) {
final ArrayList<UpdateRequestProcessorFactory> factories = new ArrayList<UpdateRequestProcessorFactory>();
if( node != null ) {
// Load and initialize the plugin chain
@ -62,7 +63,7 @@ public class ChainedUpdateProcessorFactory extends UpdateRequestProcessorFactory
= new AbstractPluginLoader<UpdateRequestProcessorFactory>( "processor chain", false, false ) {
@Override
protected void init(UpdateRequestProcessorFactory plugin, Node node) throws Exception {
plugin.init( node );
plugin.init( core, node );
}
@Override
@ -74,7 +75,7 @@ public class ChainedUpdateProcessorFactory extends UpdateRequestProcessorFactory
XPath xpath = XPathFactory.newInstance().newXPath();
try {
loader.load( (NodeList) xpath.evaluate( "chain", node, XPathConstants.NODESET ) );
loader.load( core.getSolrConfig(), (NodeList) xpath.evaluate( "chain", node, XPathConstants.NODESET ) );
}
catch (XPathExpressionException e) {
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,

View File

@ -25,6 +25,7 @@ import java.util.logging.Level;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.DOMUtil;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrQueryResponse;
import org.apache.solr.update.AddUpdateCommand;
@ -45,7 +46,7 @@ public class LogUpdateProcessorFactory extends UpdateRequestProcessorFactory {
int maxNumToLog = 8;
@Override
public void init( Node node ) {
public void init( final SolrCore core, final Node node ) {
if( node != null ) {
NamedList<Object> args = DOMUtil.childNodesToNamedList( node );
SolrParams params = SolrParams.toSolrParams( args );

View File

@ -19,6 +19,7 @@ package org.apache.solr.update.processor;
import java.io.IOException;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrQueryResponse;
import org.apache.solr.update.AddUpdateCommand;
@ -38,7 +39,7 @@ import org.w3c.dom.Node;
public class RunUpdateProcessorFactory extends UpdateRequestProcessorFactory
{
@Override
public void init( Node node ) {
public void init( final SolrCore core, final Node node ) {
}

View File

@ -17,6 +17,7 @@
package org.apache.solr.update.processor;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrQueryResponse;
import org.w3c.dom.Node;
@ -28,7 +29,7 @@ import org.w3c.dom.Node;
*/
public abstract class UpdateRequestProcessorFactory
{
public void init( Node node )
public void init( final SolrCore core, final Node node )
{
// could process the Node
}

View File

@ -78,11 +78,9 @@ public abstract class AbstractPluginLoader<T>
* @param node - the XML node defining this plugin
*/
@SuppressWarnings("unchecked")
protected T create( SolrCore core, String name, String className, Node node ) throws Exception
protected T create( Config config, String name, String className, Node node ) throws Exception
{
if (core != null)
return (T) core.createInstance(className, null, "plug-in");
return (T) Config.newInstance( className, getDefaultPackages() );
return (T) config.newInstance( className, getDefaultPackages() );
}
/**
@ -123,10 +121,7 @@ public abstract class AbstractPluginLoader<T>
* If a default element is defined, it will be returned from this function.
*
*/
public T load( NodeList nodes ) {
return load(null, nodes);
}
public T load( SolrCore core, NodeList nodes )
public T load( Config config, NodeList nodes )
{
List<PluginInitInfo> info = new ArrayList<PluginInitInfo>();
T defaultPlugin = null;
@ -142,7 +137,7 @@ public abstract class AbstractPluginLoader<T>
String className = DOMUtil.getAttr(node,"class", type);
String defaultStr = DOMUtil.getAttr(node,"default", null );
T plugin = create(core, name, className, node );
T plugin = create(config, name, className, node );
log.info("created "+name+": " + plugin.getClass().getName() );
// Either initialize now or wait till everything has been registered

View File

@ -19,6 +19,7 @@ package org.apache.solr.update.processor;
import org.apache.solr.common.util.DOMUtil;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrQueryResponse;
import org.apache.solr.update.processor.UpdateRequestProcessor;
@ -34,7 +35,7 @@ public class CustomUpdateRequestProcessorFactory extends UpdateRequestProcessorF
public NamedList args = null;
@Override
public void init( Node node )
public void init( final SolrCore core, final Node node )
{
if( node != null ) {
args = DOMUtil.childNodesToNamedList( node );

View File

@ -19,26 +19,22 @@
<config>
<requestHandler name="custom" class="solr.CustomUpdateRequestHandler" >
<str name="update.processor.factory">custom</str>
</requestHandler>
<updateRequestProcessor>
<factory name="standard" class="solr.ChainedUpdateProcessorFactory" >
<chain class="solr.LogUpdateProcessorFactory" >
<int name="maxNumToLog">100</int>
<int name="maxNumToLog">100</int>
</chain>
<chain class="solr.CustomUpdateRequestProcessorFactory" >
<lst name="name">
<str name="n1">x1</str>
<str name="n2">x2</str>
</lst>
<lst name="name">
<str name="n1">x1</str>
<str name="n2">x2</str>
</lst>
</chain>
<chain class="solr.CustomUpdateRequestProcessorFactory" >
<lst name="name">
<str name="nA">xA</str>
<str name="nA">xA</str>
</lst>
<lst name="name">
<str name="nA">xA</str>
<str name="nA">xA</str>
</lst>
</chain>
</factory>

View File

@ -100,16 +100,16 @@ public class DirectSolrConnection
}
}
// Set the instance directory
if( instanceDir != null ) {
if( Config.isInstanceDirInitialized() ) {
String dir = Config.getInstanceDir();
if( !dir.equals( instanceDir ) ) {
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, "already initalized: "+dir );
}
}
Config.setInstanceDir( instanceDir );
}
// TODO! Set the instance directory
// if( instanceDir != null ) {
// if( Config.isInstanceDirInitialized() ) {
// String dir = Config.getInstanceDir();
// if( !dir.equals( instanceDir ) ) {
// throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, "already initalized: "+dir );
// }
// }
// Config.setInstanceDir( instanceDir );
// }
SolrConfig config = SolrConfig.createInstance("solrconfig.xml");
// If the Data directory is specified, initialize SolrCore directly
@ -129,7 +129,6 @@ public class DirectSolrConnection
*
* String json = solr.request( "/select?qt=dismax&wt=json&q=...", null );
* String xml = solr.request( "/update", "&lt;add><doc><field ..." );
*
*/
public String request( String pathAndParams, String body ) throws Exception
{