You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2021/09/22 10:10:01 UTC

[jena] branch main updated: Refactor - isolate HttpServletRequest/Response inside HttpAction

This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/main by this push:
     new fbcfae7  Refactor - isolate HttpServletRequest/Response inside HttpAction
     new dc82944  Merge pull request #1074 from afs/fuseki-connectors
fbcfae7 is described below

commit fbcfae7ffefe5ecd88ec3347119a094297bfcad1
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Mon Sep 13 15:40:55 2021 +0100

    Refactor - isolate HttpServletRequest/Response inside HttpAction
---
 .../main/java/org/apache/jena/atlas/io}/IOX.java   | 142 ++++++++-------------
 jena-cmds/pom.xml                                  |   4 +-
 .../java/org/apache/jena/dboe/sys/FileLib.java     |   3 -
 .../main/java/org/apache/jena/dboe/sys/IO_DB.java  | 106 +++++++++++++++
 .../java/org/apache/jena/tdb2/sys/DatabaseOps.java |  16 ++-
 .../org/apache/jena/tdb2/sys/TestDatabaseOps.java  |   5 +-
 .../apache/jena/fuseki/access/DataAccessCtl.java   |   2 +-
 .../org/apache/jena/fuseki/ctl/ActionCompact.java  |   2 +-
 .../jena/fuseki/ctl/ActionContainerItem.java       |   2 +-
 .../java/org/apache/jena/fuseki/ctl/ActionCtl.java |   2 +-
 .../org/apache/jena/fuseki/ctl/ActionSleep.java    |   2 +-
 .../org/apache/jena/fuseki/ctl/ActionTasks.java    |   2 +-
 .../java/org/apache/jena/fuseki/ctl/Async.java     |   4 +-
 .../prometheus/PrometheusMetricsProvider.java      |   6 +-
 .../org/apache/jena/fuseki/server/RequestLog.java  |   4 +-
 .../apache/jena/fuseki/servlets/ActionExecLib.java |  19 ++-
 .../org/apache/jena/fuseki/servlets/ActionLib.java |  88 +++++++------
 .../apache/jena/fuseki/servlets/ActionREST.java    |   7 +-
 .../org/apache/jena/fuseki/servlets/GSPLib.java    |  12 +-
 .../org/apache/jena/fuseki/servlets/GSP_Base.java  |   4 +-
 .../org/apache/jena/fuseki/servlets/GSP_R.java     |  16 +--
 .../org/apache/jena/fuseki/servlets/GSP_RW.java    |   8 +-
 .../apache/jena/fuseki/servlets/GraphTarget.java   |  10 +-
 .../apache/jena/fuseki/servlets/HttpAction.java    | 137 ++++++++++++++++++--
 .../jena/fuseki/servlets/ResponseDataset.java      |  11 +-
 .../apache/jena/fuseki/servlets/ResponseJson.java  |  23 ++--
 .../apache/jena/fuseki/servlets/ResponseOps.java   |   2 +-
 .../jena/fuseki/servlets/ResponseResultSet.java    |  10 +-
 .../jena/fuseki/servlets/SHACL_Validation.java     |   4 +-
 .../jena/fuseki/servlets/SPARQLProtocol.java       |   4 +-
 .../jena/fuseki/servlets/SPARQLQueryProcessor.java |  21 ++-
 .../apache/jena/fuseki/servlets/SPARQL_Update.java |  31 ++---
 .../apache/jena/fuseki/servlets/SPARQL_Upload.java |  12 +-
 .../apache/jena/fuseki/servlets/ServletOps.java    |  21 ++-
 .../apache/jena/fuseki/system/FusekiNetLib.java    |   2 +-
 .../java/org/apache/jena/fuseki/system/Upload.java |  10 +-
 .../apache/jena/fuseki/system/spot/SpotTDB2.java   |   8 +-
 .../apache/jena/fuseki/main/CustomTestService.java |  16 +--
 .../fuseki/main/TestFusekiCustomOperation.java     |  16 +--
 .../jena/fuseki/main/examples/DemoService.java     |  16 +--
 .../main/examples/InitFusekiCustomOperation.java   |   6 +-
 .../apache/jena/fuseki/mgt/ActionBackupList.java   |   2 +-
 .../org/apache/jena/fuseki/mgt/ActionDatasets.java |  14 +-
 .../org/apache/jena/fuseki/mgt/ActionLogs.java     |   8 +-
 .../apache/jena/fuseki/mgt/ActionServerStatus.java |   8 +-
 45 files changed, 514 insertions(+), 334 deletions(-)

diff --git a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/IOX.java b/jena-base/src/main/java/org/apache/jena/atlas/io/IOX.java
similarity index 65%
rename from jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/IOX.java
rename to jena-base/src/main/java/org/apache/jena/atlas/io/IOX.java
index 2bd8f34..cde6fed 100644
--- a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/IOX.java
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/IOX.java
@@ -16,36 +16,25 @@
  * limitations under the License.
  */
 
-package org.apache.jena.tdb2.sys;
+package org.apache.jena.atlas.io;
 
 import java.io.BufferedOutputStream;
-import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.nio.file.attribute.FileAttribute;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Objects;
 import java.util.function.Function;
-import java.util.regex.Pattern;
 
 import org.apache.jena.atlas.RuntimeIOException;
 import org.apache.jena.atlas.logging.FmtLog;
-import org.apache.jena.dboe.DBOpEnvException;
-import org.apache.jena.dboe.base.file.Location;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-/**
- *  PathX
- */
 public class IOX {
 
     public static final Path currentDirectory = Paths.get(".");
 
     /** A Consumer that can throw {@link IOException}. */
+    @FunctionalInterface
     public interface IOConsumer<X> {
         void actionEx(X arg) throws IOException;
     }
@@ -76,10 +65,25 @@ public class IOX {
     public static RuntimeIOException exception(String message, IOException ioException) {
         return new RuntimeIOException(message, ioException);
     }
+    
+    /** Run IO code */
+    @FunctionalInterface
+    public interface ActionIO { void run() throws IOException; }
+
+    /** Run an action, converting an {@link IOException} into a {@link RuntimeIOException}.
+     * <p>
+     * Idiom:
+     * <pre>
+     *     run(()-&gt;...));
+     * </pre>
+     */
+    public static void run(ActionIO action) {
+        try { action.run(); }
+        catch (IOException e) { throw exception(e); }
+    }
 
     /** Write a file safely - the change happens (the function returns true) or
      * something went wrong (the function throws a runtime exception) and the file is not changed.
-     * Note that the tempfile must be in the same direct as the actual file so an OS-atomic rename can be done.
      */
     public static boolean safeWrite(Path file, IOConsumer<OutputStream> writerAction) {
         Path tmp = createTempFile(file.getParent(), file.getFileName().toString(), ".tmp");
@@ -117,6 +121,36 @@ public class IOX {
             throw IOX.exception(ex);
         }
     }
+    
+    public static void deleteAll(String start) {
+        deleteAll(Paths.get(start));
+    }
+
+    /** Delete everything from a {@code Path} start point, including the path itself.
+     * Works on files or directories.
+     * Walks down the tree and deletes directories on the way backup.
+     */
+    public static void deleteAll(Path start) {
+        try {
+            Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
+                @Override
+                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                    Files.delete(file);
+                    return FileVisitResult.CONTINUE;
+                }
+                @Override
+                public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException {
+                    if (e == null) {
+                        Files.delete(dir);
+                        return FileVisitResult.CONTINUE;
+                    } else {
+                        throw e;
+                    }
+                }
+            });
+        }
+        catch (IOException ex) { throw IOX.exception(ex) ; }
+    }
 
     /** Copy a file, not atomic. *
      * Can copy to a directory or over an existing file.
@@ -139,7 +173,7 @@ public class IOX {
         }
     }
 
-    /** Create a directory - thgrow a runtime exception if there are any problems.
+    /** Create a directory - throw a runtime exception if there are any problems.
      * This function wraps {@code Files.createDirectory}.
      */
     public static void createDirectory(Path dir) {
@@ -147,33 +181,6 @@ public class IOX {
         catch (IOException ex) { throw IOX.exception(ex); }
     }
 
-    /** Convert a {@link Path}  to a {@link Location}. */
-    public static Location asLocation(Path path) {
-        Objects.requireNonNull(path, "IOX.asLocation(null)");
-        if ( ! Files.isDirectory(path) )
-            throw new RuntimeIOException("Path is not naming a directory: "+path);
-        return Location.create(path.toString());
-    }
-
-//    /** Convert a {@link org.apache.jena.tdb.base.file.Location} to a {@link Path}. */
-//    public static Path asPath(org.apache.jena.tdb.base.file.Location location) {
-//        if ( location.isMem() )
-//            throw new RuntimeIOException("Location is a memory location: "+location);
-//        return Paths.get(location.getDirectoryPath());
-//    }
-
-    /** Convert a {@link Location} to a {@link Path}. */
-    public static Path asPath(org.apache.jena.dboe.base.file.Location location) {
-        if ( location.isMem() )
-            throw new RuntimeIOException("Location is a memory location: "+location);
-        return Paths.get(location.getDirectoryPath());
-    }
-
-    /** Convert a {@link Location} to a {@link File}. */
-    public static File asFile(Location loc) {
-        return new File(loc.getDirectoryPath());
-    }
-
     /** Read the whole of a file */
     public static byte[] readAll(Path pathname) {
         try {
@@ -242,53 +249,4 @@ public class IOX {
         }
         return null;
     }
-
-    private static Logger LOG = LoggerFactory.getLogger(Util.class);
-
-    /** Find the files in this directory that have namebase as a prefix and
-     *  are then numbered.
-     *  <p>
-     *  Returns a sorted list from, low to high index.
-     */
-    public static List<Path> scanForDirByPattern(Path directory, String namebase, String nameSep) {
-        Pattern pattern = Pattern.compile(Pattern.quote(namebase)+
-                                          Pattern.quote(nameSep)+
-                                          "[\\d]+");
-        List<Path> paths = new ArrayList<>();
-        try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory, namebase + "*")) {
-            for ( Path entry : stream ) {
-                if ( !pattern.matcher(entry.getFileName().toString()).matches() ) {
-                    throw new DBOpEnvException("Invalid filename for matching: "+entry.getFileName());
-                    // Alternative: Skip bad trailing parts but more likely there is a naming problem.
-                    //   LOG.warn("Invalid filename for matching: {} skipped", entry.getFileName());
-                    //   continue;
-                }
-                // Follows symbolic links.
-                if ( !Files.isDirectory(entry) )
-                    throw new DBOpEnvException("Not a directory: "+entry);
-                paths.add(entry);
-            }
-        }
-        catch (IOException ex) {
-            FmtLog.warn(LOG, "Can't inspect directory: (%s, %s)", directory, namebase);
-            throw new DBOpEnvException(ex);
-        }
-        Comparator<Path> comp = (f1, f2) -> {
-            int num1 = extractIndex(f1.getFileName().toString(), namebase, nameSep);
-            int num2 = extractIndex(f2.getFileName().toString(), namebase, nameSep);
-            return Integer.compare(num1, num2);
-        };
-        paths.sort(comp);
-        //indexes.sort(Long::compareTo);
-        return paths;
-    }
-
-    /** Given a filename in "base-NNNN" format, return the value of NNNN */
-    public static int extractIndex(String name, String namebase, String nameSep) {
-        int i = namebase.length()+nameSep.length();
-        String numStr = name.substring(i);
-        int num = Integer.parseInt(numStr);
-        return num;
-    }
-
 }
diff --git a/jena-cmds/pom.xml b/jena-cmds/pom.xml
index 259dce5..c9fb4f7 100644
--- a/jena-cmds/pom.xml
+++ b/jena-cmds/pom.xml
@@ -108,12 +108,14 @@
       <!-- This module can be used as a dependency downstream -->
       <optional>true</optional>
     </dependency>
+
+    <!--
     <dependency>
-      <!-- Titanium -->
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-jdk14</artifactId>
       <optional>true</optional>
     </dependency>
+    -->
 
     <dependency>
       <groupId>junit</groupId>
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/sys/FileLib.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/sys/FileLib.java
index 54cdfab..e2f25d6 100644
--- a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/sys/FileLib.java
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/sys/FileLib.java
@@ -27,11 +27,8 @@ import org.apache.jena.atlas.io.IO;
 import org.apache.jena.dboe.base.file.ChannelManager;
 import org.apache.jena.dboe.base.file.FileException;
 
-// => IO
 public class FileLib
 {
-    // Check whether still used.
-
     public static FileChannel openUnmanaged(String filename) {
         return openUnmanaged(filename, "rw");
     }
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/sys/IO_DB.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/sys/IO_DB.java
new file mode 100644
index 0000000..52e4ea3
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/sys/IO_DB.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.dboe.sys;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
+import java.util.regex.Pattern;
+
+import org.apache.jena.atlas.RuntimeIOException;
+import org.apache.jena.atlas.logging.FmtLog;
+import org.apache.jena.dboe.DBOpEnvException;
+import org.apache.jena.dboe.base.file.Location;
+
+public class IO_DB {
+    // Location == org.apache.jena.dboe.base.file.Location
+    
+    /** Convert a {@link Path}  to a {@link Location}. */
+    public static Location asLocation(Path path) {
+        Objects.requireNonNull(path, "IOX.asLocation(null)");
+        if ( ! Files.isDirectory(path) )
+            throw new RuntimeIOException("Path is not naming a directory: "+path);
+        return Location.create(path.toString());
+    }
+
+    /** Convert a {@link Location} to a {@link Path}. */
+    public static Path asPath(Location location) {
+        if ( location.isMem() )
+            throw new RuntimeIOException("Location is a memory location: "+location);
+        return Paths.get(location.getDirectoryPath());
+    }
+
+    /** Convert a {@link Location} to a {@link File}. */
+    public static File asFile(org.apache.jena.dboe.base.file.Location loc) {
+        return new File(loc.getDirectoryPath());
+    }
+
+    /** Find the files in this directory that have namebase as a prefix and
+     *  are then numbered.
+     *  <p>
+     *  Returns a sorted list from, low to high index.
+     */
+    public static List<Path> scanForDirByPattern(Path directory, String namebase, String nameSep) {
+        Pattern pattern = Pattern.compile(Pattern.quote(namebase)+
+                                          Pattern.quote(nameSep)+
+                                          "[\\d]+");
+        List<Path> paths = new ArrayList<>();
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory, namebase + "*")) {
+            for ( Path entry : stream ) {
+                if ( !pattern.matcher(entry.getFileName().toString()).matches() ) {
+                    throw new DBOpEnvException("Invalid filename for matching: "+entry.getFileName());
+                    // Alternative: Skip bad trailing parts but more likely there is a naming problem.
+                    //   LOG.warn("Invalid filename for matching: {} skipped", entry.getFileName());
+                    //   continue;
+                }
+                // Follows symbolic links.
+                if ( !Files.isDirectory(entry) )
+                    throw new DBOpEnvException("Not a directory: "+entry);
+                paths.add(entry);
+            }
+        }
+        catch (IOException ex) {
+            FmtLog.warn(IO_DB.class, "Can't inspect directory: (%s, %s)", directory, namebase);
+            throw new DBOpEnvException(ex);
+        }
+        Comparator<Path> comp = (f1, f2) -> {
+            int num1 = extractIndex(f1.getFileName().toString(), namebase, nameSep);
+            int num2 = extractIndex(f2.getFileName().toString(), namebase, nameSep);
+            return Integer.compare(num1, num2);
+        };
+        paths.sort(comp);
+        //indexes.sort(Long::compareTo);
+        return paths;
+    }
+
+    /** Given a filename in "base-NNNN" format, return the value of NNNN */
+    public static int extractIndex(String name, String namebase, String nameSep) {
+        int i = namebase.length()+nameSep.length();
+        String numStr = name.substring(i);
+        int num = Integer.parseInt(numStr);
+        return num;
+    }
+}
diff --git a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOps.java b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOps.java
index d04f54e..f9de048 100644
--- a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOps.java
+++ b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOps.java
@@ -26,10 +26,12 @@ import java.util.stream.Stream;
 import java.util.zip.GZIPOutputStream;
 
 import org.apache.jena.atlas.RuntimeIOException;
+import org.apache.jena.atlas.io.IOX;
 import org.apache.jena.atlas.lib.DateTimeUtils;
 import org.apache.jena.atlas.lib.Pair;
 import org.apache.jena.atlas.logging.Log;
 import org.apache.jena.dboe.base.file.Location;
+import org.apache.jena.dboe.sys.IO_DB;
 import org.apache.jena.dboe.sys.Names;
 import org.apache.jena.dboe.transaction.txn.TransactionCoordinator;
 import org.apache.jena.dboe.transaction.txn.TransactionalSystem;
@@ -87,14 +89,14 @@ public class DatabaseOps {
         // Exists?
         if ( ! location.exists() )
             throw new TDBException("No such location: "+location);
-        Path path = IOX.asPath(location);
+        Path path = IO_DB.asPath(location);
         // Scan for DBs
         Path db = findLocation(path, dbPrefix);
         if ( db == null ) {
             db = path.resolve(dbPrefix+SEP+startCount);
             IOX.createDirectory(db);
         }
-        Location loc2 = IOX.asLocation(db);
+        Location loc2 = IO_DB.asLocation(db);
         DatasetGraphTDB dsg = StoreConnection.connectCreate(loc2, params).getDatasetGraphTDB();
         DatasetGraphSwitchable appDSG = new DatasetGraphSwitchable(path, location, dsg);
         return appDSG;
@@ -183,7 +185,7 @@ public class DatabaseOps {
             Path db1 = findLocation(base, dbPrefix);
             if ( db1 == null )
                 throw new TDBException("No location: ("+base+", "+dbPrefix+")");
-            Location loc1 = IOX.asLocation(db1);
+            Location loc1 = IO_DB.asLocation(db1);
 
             // -- Checks
             Location loc1a = ((DatasetGraphTDB)container.get()).getLocation();
@@ -197,18 +199,18 @@ public class DatabaseOps {
             // -- Checks
 
             // Version
-            int v = IOX.extractIndex(db1.getFileName().toString(), dbPrefix, SEP);
+            int v = IO_DB.extractIndex(db1.getFileName().toString(), dbPrefix, SEP);
             String next = FilenameUtils.filename(dbPrefix, SEP, v+1);
 
             Path db2 = db1.getParent().resolve(next);
             IOX.createDirectory(db2);
-            Location loc2 = IOX.asLocation(db2);
+            Location loc2 = IO_DB.asLocation(db2);
             LOG.debug(String.format("Compact %s -> %s\n", db1.getFileName(), db2.getFileName()));
 
             compact(container, loc1, loc2);
 
             if ( shouldDeleteOld ) {
-                Path loc1Path = IOX.asPath(loc1);
+                Path loc1Path = IO_DB.asPath(loc1);
                 LOG.debug("Deleting old database after successful compaction (old db path='" + loc1Path + "')...");
 
                 try (Stream<Path> walk = Files.walk(loc1Path)){
@@ -307,7 +309,7 @@ public class DatabaseOps {
         if ( ! Files.exists(directory) )
             return null;
         // In-order, low to high.
-        List<Path> maybe = IOX.scanForDirByPattern(directory, namebase, SEP);
+        List<Path> maybe = IO_DB.scanForDirByPattern(directory, namebase, SEP);
         return Util.getLastOrNull(maybe);
     }
 }
diff --git a/jena-db/jena-tdb2/src/test/java/org/apache/jena/tdb2/sys/TestDatabaseOps.java b/jena-db/jena-tdb2/src/test/java/org/apache/jena/tdb2/sys/TestDatabaseOps.java
index 6814297..cf5e804 100644
--- a/jena-db/jena-tdb2/src/test/java/org/apache/jena/tdb2/sys/TestDatabaseOps.java
+++ b/jena-db/jena-tdb2/src/test/java/org/apache/jena/tdb2/sys/TestDatabaseOps.java
@@ -25,6 +25,7 @@ import org.apache.commons.io.FileUtils;
 import org.apache.jena.atlas.lib.FileOps;
 import org.apache.jena.base.Sys;
 import org.apache.jena.dboe.base.file.Location;
+import org.apache.jena.dboe.sys.IO_DB;
 import org.apache.jena.graph.Graph;
 import org.apache.jena.graph.Triple;
 import org.apache.jena.riot.RDFDataMgr;
@@ -62,7 +63,7 @@ public class TestDatabaseOps
     @After
     public void after() {
         TDBInternal.reset();
-        FileUtils.deleteQuietly(IOX.asFile(dir));
+        FileUtils.deleteQuietly(IO_DB.asFile(dir));
     }
 
     @Test public void compact_dsg_1() {
@@ -236,7 +237,7 @@ public class TestDatabaseOps
         // This is a long standing JDK issue.
         // https://bugs.openjdk.java.net/browse/JDK-4715154
         if ( ! Sys.isWindows )
-            assertFalse(IOX.asFile(loc1).exists());
+            assertFalse(IO_DB.asFile(loc1).exists());
 
         DatasetGraph dsg2 = dsgs.get();
         Location loc2 = ((DatasetGraphTDB)dsg2).getLocation();
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
index bfa5853..30177c7 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
@@ -60,7 +60,7 @@ public class DataAccessCtl {
      * Get the user from {@code ?user} query string parameter. Use carefully; for situations where the user name has
      * been authenticated already and is being passed on securely. Also for testing.
      */
-    public static final Function<HttpAction, String> paramUserServlet = (action)->action.request.getParameter("user");
+    public static final Function<HttpAction, String> paramUserServlet = (action)->action.getRequestParameter("user");
 
     /**
      * Add data access control information on a {@link DatasetGraph}. This modifies the
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionCompact.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionCompact.java
index a7234ca..b11e1c5 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionCompact.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionCompact.java
@@ -95,7 +95,7 @@ public class ActionCompact extends ActionAsyncTask
         public CompactTask(HttpAction action) {
             super(action);
 
-            String deleteOldParam = action.request.getParameter("deleteOld");
+            String deleteOldParam = action.getRequestParameter("deleteOld");
 
             this.shouldDeleteOld = ( deleteOldParam != null
                                      && ( deleteOldParam.isEmpty() || deleteOldParam.equalsIgnoreCase("true") ) );
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionContainerItem.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionContainerItem.java
index 1d8c0e7..c4261da 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionContainerItem.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionContainerItem.java
@@ -36,7 +36,7 @@ public abstract class ActionContainerItem extends ActionCtl {
     @Override
     final
     public void execute(HttpAction action) {
-        String method = action.request.getMethod();
+        String method = action.getRequestMethod();
         if ( method.equals(METHOD_GET) )
             performGet(action);
         else if ( method.equals(METHOD_POST) )
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionCtl.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionCtl.java
index 9742452..3fa0942 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionCtl.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionCtl.java
@@ -52,7 +52,7 @@ public abstract class ActionCtl extends ServletProcessor implements ActionLifecy
 
     /** Get the item name - the part after the URI for the servlet (which is the container). */
     public static String getItemName(HttpAction action) {
-        return action.request.getPathInfo();
+        return action.getRequestPathInfo();
     }
 
     /**
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionSleep.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionSleep.java
index ab47f03..10c563c 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionSleep.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionSleep.java
@@ -60,7 +60,7 @@ public class ActionSleep extends ActionCtl /* Not ActionAsyncTask - that is a co
     }
 
     protected SleepTask createRunnable(HttpAction action) {
-        String interval = action.request.getParameter("interval");
+        String interval = action.getRequestParameter("interval");
         int sleepMilli = 5000;
         if ( interval != null ) {
             try {
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionTasks.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionTasks.java
index b674294..1e57a79 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionTasks.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionTasks.java
@@ -57,7 +57,7 @@ public class ActionTasks extends ActionCtl
                 action.log.warn("Unexpected task name : "+name);
         }
 
-        String method = action.request.getMethod();
+        String method = action.getRequestMethod();
         if ( method.equals(METHOD_GET) )
             execGet(action, name);
         else if ( method.equals(METHOD_POST) )
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/Async.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/Async.java
index 08fb62a..702147d 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/Async.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/Async.java
@@ -44,11 +44,11 @@ public class Async
     }
 
     private static void setLocationHeader(HttpAction action, AsyncTask asyncTask) {
-        String x = action.getRequest().getRequestURI();
+        String x = action.getRequestRequestURI();
         if ( ! x.endsWith("/") )
             x += "/";
         x += asyncTask.getTaskId();
-        action.getResponse().setHeader(HttpHeaders.LOCATION, x);
+        action.setResponseHeader(HttpHeaders.LOCATION, x);
     }
 
     public static AsyncTask execASyncTask(HttpAction action, AsyncPool asyncPool, String displayName, Runnable runnable) {
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/prometheus/PrometheusMetricsProvider.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/prometheus/PrometheusMetricsProvider.java
index 580a135..204ae93 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/prometheus/PrometheusMetricsProvider.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/prometheus/PrometheusMetricsProvider.java
@@ -67,10 +67,10 @@ public class PrometheusMetricsProvider implements MetricsProvider {
 
     @Override
     public void scrape(HttpAction action) {
-        try (ServletOutputStream out = action.response.getOutputStream()) {
+        try (ServletOutputStream out = action.getResponseOutputStream()) {
             ServletOps.success(action);
-            action.response.setContentType( WebContent.contentTypeTextPlain );
-            action.response.setCharacterEncoding( WebContent.charsetUTF8 );
+            action.setResponseContentType( WebContent.contentTypeTextPlain );
+            action.setResponseCharacterEncoding( WebContent.charsetUTF8 );
 
             out.write( meterRegistry.scrape().getBytes() );
         } catch (Throwable t) {
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/RequestLog.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/RequestLog.java
index 86a1ff3..06e0679 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/RequestLog.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/RequestLog.java
@@ -67,8 +67,8 @@ NCSA extended/combined log format
      * xxx.xxx.xxx.xxx - - [01/Feb/2014:03:19:09 +0000] "GET / HTTP/1.1" 200 6190  "-" "check_http/v1.4.16 (nagios-plugins 1.4.16)"
      */
     public static String combinedNCSA(HttpAction action) {
-        HttpServletRequest request = action.request;
-        HttpServletResponse response = action.response;
+        HttpServletRequest request = action.getRequest();
+        HttpServletResponse response = action.getResponse();
         return combinedNCSA(request, response);
     }
 
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionExecLib.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionExecLib.java
index cd4fc0f..0f86022 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionExecLib.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionExecLib.java
@@ -90,7 +90,7 @@ public class ActionExecLib {
             logRequest(action);
             action.setStartTime();
             initResponse(action);
-            HttpServletResponse response = action.response;
+            HttpServletResponse response = action.getResponse();
 
             startRequest(action);
 
@@ -196,7 +196,7 @@ public class ActionExecLib {
      *            Request ID
      */
     public static void addRequestId(HttpServletResponse response, long id) {
-        response.addHeader(Fuseki.FusekiRequestIdHeader, Long.toString(id));
+        response.setHeader(Fuseki.FusekiRequestIdHeader, Long.toString(id));
     }
 
     /**
@@ -220,16 +220,16 @@ public class ActionExecLib {
 
     /** Log an {@link HttpAction} request. */
     public static void logRequest(HttpAction action) {
-        String url = ActionLib.wholeRequestURL(action.request);
-        String method = action.request.getMethod();
+        String url = ActionLib.wholeRequestURL(action.getRequest());
+        String method = action.getRequestMethod();
 
         if ( logLifecycle(action) )
             FmtLog.info(action.log, "[%d] %s %s", action.id, method, url);
         if ( action.verbose ) {
-            Enumeration<String> en = action.request.getHeaderNames();
+            Enumeration<String> en = action.getRequestHeaderNames();
             for (; en.hasMoreElements();) {
                 String h = en.nextElement();
-                Enumeration<String> vals = action.request.getHeaders(h);
+                Enumeration<String> vals = action.getRequestHeaders(h);
                 if ( !vals.hasMoreElements() )
                     FmtLog.info(action.log, "[%d]   => %s", action.id, h+":");
                 else {
@@ -247,7 +247,6 @@ public class ActionExecLib {
     public static void logResponse(HttpAction action) {
         long time = action.getTime();
 
-        HttpServletResponseTracker response = action.response;
         if ( action.verbose ) {
             if ( action.responseContentType != null )
                 FmtLog.info(action.log,"[%d]   <= %-20s %s", action.id, HttpNames.hContentType+":", action.responseContentType);
@@ -290,11 +289,11 @@ public class ActionExecLib {
 
     /** Set headers for the response. */
     public static void initResponse(HttpAction action) {
-        ServletBase.setCommonHeaders(action.response);
-        String method = action.request.getMethod();
+        ActionLib.setCommonHeaders(action);
+        String method = action.getRequestMethod();
         // All GET and HEAD operations are sensitive to conneg so ...
         if ( HttpNames.METHOD_GET.equalsIgnoreCase(method) || HttpNames.METHOD_HEAD.equalsIgnoreCase(method) )
-            ServletBase.setVaryHeader(action.response);
+            ServletBase.setVaryHeader(action.getResponse());
     }
 
     /**
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionLib.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionLib.java
index 1faa35a..66f1bd3 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionLib.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionLib.java
@@ -28,6 +28,7 @@ import java.nio.charset.CharacterCodingException;
 import java.util.Objects;
 import java.util.function.BiConsumer;
 
+import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -128,7 +129,7 @@ public class ActionLib {
         return ds;
     }
 
-    /** Calculate the fill URL including query string
+    /** Calculate the full URL including query string
      * for the HTTP request. This may be quite long.
      * @param request HttpServletRequest
      * @return String The full URL, including query string.
@@ -152,8 +153,7 @@ public class ActionLib {
      * "/APP/dataset/server" becomes "/dataset/server"
      */
     public static String removeContextPath(HttpAction action) {
-
-        return actionURI(action.request);
+        return actionURI(action.getRequest());
     }
 
     /**
@@ -166,7 +166,11 @@ public class ActionLib {
 //      ServletContext cxt = this.getServletContext();
 //      Log.info(this, "ServletContext path     = '"+cxt.getContextPath()+"'");
 
-        String contextPath = request.getServletContext().getContextPath();
+        ServletContext servletCxt = request.getServletContext();
+        if ( servletCxt == null )
+            return request.getRequestURI();
+                    
+        String contextPath = servletCxt.getContextPath();
         String uri = request.getRequestURI();
         if ( contextPath == null )
             return uri;
@@ -180,13 +184,13 @@ public class ActionLib {
 
     /** Negotiate the content-type and set the response headers */
     public static MediaType contentNegotation(HttpAction action, AcceptList myPrefs, MediaType defaultMediaType) {
-        MediaType mt = ConNeg.chooseContentType(action.request, myPrefs, defaultMediaType);
+        MediaType mt = ConNeg.chooseContentType(action.getRequest(), myPrefs, defaultMediaType);
         if ( mt == null )
             return null;
         if ( mt.getContentTypeStr() != null )
-            action.response.setContentType(mt.getContentTypeStr());
+            action.setResponseContentType(mt.getContentTypeStr());
         if ( mt.getCharset() != null )
-            action.response.setCharacterEncoding(mt.getCharset());
+            action.setResponseCharacterEncoding(mt.getCharset());
         return mt;
     }
 
@@ -221,7 +225,7 @@ public class ActionLib {
      */
     public static void parse(HttpAction action, StreamRDF dest, Lang lang, String base) {
         InputStream input = null;
-        try { input = action.request.getInputStream(); }
+        try { input = action.getRequestInputStream(); }
         catch (IOException ex) { IO.exception(ex); }
         parse(action, dest, input, lang, base);
     }
@@ -254,9 +258,9 @@ public class ActionLib {
      * If there is a no {@code Content-Length} header, no need to do anything - the connection is not reusable.
      */
     public static void consumeBody(HttpAction action) {
-        if ( action.request.getContentLengthLong() > 0 ) {
+        if ( action.getRequestContentLengthLong() > 0 ) {
             try {
-                IO.skipToEnd(action.request.getInputStream());
+                IO.skipToEnd(action.getRequestInputStream());
             } catch (IOException ex) {}
         }
     }
@@ -334,7 +338,7 @@ public class ActionLib {
             ct = lang.getContentType().toHeaderString();
 
         try {
-            OutputStream out = action.response.getOutputStream();
+            OutputStream out = action.getResponseOutputStream();
             // Do not use try-finally here. Error handling headers are written later.
             // RDF/XML can go wrong during writing so we buffered to know it will succeed when we produce the output bytes.
             // (Other formats are much less prone to this.)
@@ -351,13 +355,13 @@ public class ActionLib {
                     return;
                 }
                 // Succeeded in formatting the RDF
-                action.response.setContentLength(bytes.length);
-                action.response.setContentType(ct);
-                action.response.setStatus(HttpSC.OK_200);
+                action.setResponseContentLength(bytes.length);
+                action.setResponseContentType(ct);
+                action.setResponseStatus(HttpSC.OK_200);
                 out.write(bytes);
             } else {
                 // Try to write directly (streaming if possible).
-                action.response.setContentType(ct);
+                action.setResponseContentType(ct);
                 writeAction.accept(out, fmt);
             }
             out.flush();
@@ -381,16 +385,24 @@ public class ActionLib {
      * @return ContentType
      */
     public static ContentType getContentType(HttpAction action) {
-        return FusekiNetLib.getContentType(action.request);
+        return FusekiNetLib.getContentType(action.getRequest());
     }
 
-    public static void setCommonHeadersForOptions(HttpServletResponse httpResponse) {
+    public static void setCommonHeadersForOptions(HttpAction action) {
+        setCommonHeadersForOptions(action.getResponse());
+    }
+    
+    private static void setCommonHeadersForOptions(HttpServletResponse httpResponse) {
         if ( Fuseki.CORS_ENABLED )
             httpResponse.setHeader(HttpNames.hAccessControlAllowHeaders, "X-Requested-With, Content-Type, Authorization");
         setCommonHeaders(httpResponse);
     }
 
-    public static void setCommonHeaders(HttpServletResponse httpResponse) {
+    public static void setCommonHeaders(HttpAction action) {
+        setCommonHeaders(action.getResponse());
+    }
+    
+    private static void setCommonHeaders(HttpServletResponse httpResponse) {
         if ( Fuseki.CORS_ENABLED )
             httpResponse.setHeader(HttpNames.hAccessControlAllowOrigin, "*");
         if ( Fuseki.outputFusekiServerHeader )
@@ -403,19 +415,19 @@ public class ActionLib {
      * @return item name as "/name" or {@code null}
      */
     private /*unused*/ static String extractItemName(HttpAction action) {
-//          action.log.info("context path  = "+action.request.getContextPath());
-//          action.log.info("pathinfo      = "+action.request.getPathInfo());
-//          action.log.info("servlet path  = "+action.request.getServletPath());
+//          action.log.info("context path  = "+action.getRequestContextPath());
+//          action.log.info("pathinfo      = "+action.getRequestPathInfo());
+//          action.log.info("servlet path  = "+action.getRequestServletPath());
         // if /name
         //    request.getServletPath() otherwise it's null
         // if /*
         //    request.getPathInfo(); otherwise it's null.
 
         // PathInfo is after the servlet name.
-        String x1 = action.request.getServletPath();
-        String x2 = action.request.getPathInfo();
+        String x1 = action.getRequestServletPath();
+        String x2 = action.getRequestPathInfo();
 
-        String pathInfo = action.request.getPathInfo();
+        String pathInfo = action.getRequestPathInfo();
         if ( pathInfo == null || pathInfo.isEmpty() || pathInfo.equals("/") )
             // Includes calling as a container.
             return null;
@@ -431,37 +443,37 @@ public class ActionLib {
     // Packing of OPTIONS.
 
     public static void doOptionsGet(HttpAction action) {
-        ServletBase.setCommonHeadersForOptions(action.response);
-        action.response.setHeader(HttpNames.hAllow, "GET,OPTIONS");
+        setCommonHeadersForOptions(action);
+        action.setResponseHeader(HttpNames.hAllow, "GET,OPTIONS");
     }
 
     public static void doOptionsGetHead(HttpAction action) {
-        ServletBase.setCommonHeadersForOptions(action.response);
-        action.response.setHeader(HttpNames.hAllow, "GET,HEAD,OPTIONS");
+        setCommonHeadersForOptions(action);
+        action.setResponseHeader(HttpNames.hAllow, "GET,HEAD,OPTIONS");
     }
 
     public static void doOptionsGetPost(HttpAction action) {
-        ServletBase.setCommonHeadersForOptions(action.response);
-        action.response.setHeader(HttpNames.hAllow, "GET,POST,OPTIONS");
+        setCommonHeadersForOptions(action);
+        action.setResponseHeader(HttpNames.hAllow, "GET,POST,OPTIONS");
     }
 
     public static void doOptionsGetPostHead(HttpAction action) {
-        ServletBase.setCommonHeadersForOptions(action.response);
-        action.response.setHeader(HttpNames.hAllow, "GET,POST,HEAD,OPTIONS");
+        setCommonHeadersForOptions(action);
+        action.setResponseHeader(HttpNames.hAllow, "GET,POST,HEAD,OPTIONS");
     }
 
     public static void doOptionsGetPostDelete(HttpAction action) {
-        ServletBase.setCommonHeadersForOptions(action.response);
-        action.response.setHeader(HttpNames.hAllow, "GET,POST,DELETE,OPTIONS");
+        setCommonHeadersForOptions(action);
+        action.setResponseHeader(HttpNames.hAllow, "GET,POST,DELETE,OPTIONS");
     }
 
     public static void doOptionsGetPostDeleteHead(HttpAction action) {
-        ServletBase.setCommonHeadersForOptions(action.response);
-        action.response.setHeader(HttpNames.hAllow, "GET,HEAD,POST,DELETE,OPTIONS");
+        setCommonHeadersForOptions(action);
+        action.setResponseHeader(HttpNames.hAllow, "GET,HEAD,POST,DELETE,OPTIONS");
     }
 
     public static void doOptionsPost(HttpAction action) {
-        ServletBase.setCommonHeadersForOptions(action.response);
-        action.response.setHeader(HttpNames.hAllow, "POST,OPTIONS");
+        setCommonHeadersForOptions(action);
+        action.setResponseHeader(HttpNames.hAllow, "POST,OPTIONS");
     }
 }
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionREST.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionREST.java
index 80e11fd..b1bdace 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionREST.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionREST.java
@@ -23,9 +23,6 @@ import static org.apache.jena.riot.web.HttpNames.*;
 
 import java.util.Locale;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
 import org.apache.jena.fuseki.server.CounterName;
 import org.apache.jena.sparql.core.DatasetGraph;
 
@@ -39,9 +36,7 @@ public abstract class ActionREST extends ActionService
     @Override
     public void execute(HttpAction action) {
         // Intercept to put counters around calls.
-        HttpServletRequest req = action.request;
-        HttpServletResponse resp = action.response;
-        String method = req.getMethod().toUpperCase(Locale.ROOT);
+        String method = action.getRequestMethod().toUpperCase(Locale.ROOT);
 
         if (method.equals(METHOD_GET))
             doGet$(action);
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSPLib.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSPLib.java
index b8c45d6..d0ca7bd 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSPLib.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSPLib.java
@@ -28,12 +28,12 @@ public class GSPLib {
     
     /** Test whether the operation has either of the GSP parameters. */
     public static boolean hasGSPParams(HttpAction action) {
-        if ( action.request.getQueryString() == null )
+        if ( action.getRequestQueryString() == null )
             return false;
-        boolean hasParamGraphDefault = action.request.getParameter(HttpNames.paramGraphDefault) != null;
+        boolean hasParamGraphDefault = action.getRequestParameter(HttpNames.paramGraphDefault) != null;
         if ( hasParamGraphDefault )
             return true;
-        boolean hasParamGraph = action.request.getParameter(HttpNames.paramGraph) != null;
+        boolean hasParamGraph = action.getRequestParameter(HttpNames.paramGraph) != null;
         if ( hasParamGraph )
             return true;
         return false;
@@ -41,9 +41,9 @@ public class GSPLib {
 
     /** Test whether the operation has exactly one GSP parameter and no other parameters. */ 
     public static boolean hasGSPParamsStrict(HttpAction action) {
-        if ( action.request.getQueryString() == null )
+        if ( action.getRequestQueryString() == null )
             return false;
-        Map<String, String[]> params = action.request.getParameterMap();
+        Map<String, String[]> params = action.getRequestParameterMap();
         if ( params.size() != 1 )
             return false;
         boolean hasParamGraphDefault = GSPLib.hasExactlyOneValue(action, HttpNames.paramGraphDefault);
@@ -54,7 +54,7 @@ public class GSPLib {
 
     /** Check whether there is exactly one HTTP header value */
     public static boolean hasExactlyOneValue(HttpAction action, String name) {
-        String[] values = action.request.getParameterValues(name);
+        String[] values = action.getRequestParameterValues(name);
         if ( values == null )
             return false;
         if ( values.length == 0 )
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_Base.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_Base.java
index 8b4b916..2855a46 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_Base.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_Base.java
@@ -37,7 +37,7 @@ public abstract class GSP_Base extends ActionREST {
     }
     
     protected static boolean isQuads(HttpAction action) {
-        return action.request.getQueryString() == null;
+        return action.getRequestQueryString() == null;
     }
 
     private static void validateQuads(HttpAction action) { }
@@ -48,7 +48,7 @@ public abstract class GSP_Base extends ActionREST {
      * identified.
      */
     private static void validateGSP(HttpAction action) {    
-        HttpServletRequest request = action.request;
+        HttpServletRequest request = action.getRequest();
         if ( request.getQueryString() == null )
             ServletOps.errorBadRequest("No query string. ?default or ?graph required.");
 
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_R.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_R.java
index 090a6ce..46b5380 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_R.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_R.java
@@ -48,11 +48,11 @@ public class GSP_R extends GSP_Base {
     }
 
     protected void execGetQuads(HttpAction action) {
-        ActionLib.setCommonHeaders(action.response);
+        ActionLib.setCommonHeaders(action);
         // If this asks for triples, get N-Quads. Don't want the named graphs hidden.
         MediaType mediaType = ActionLib.contentNegotationQuads(action);
         ServletOutputStream output;
-        try { output = action.response.getOutputStream(); }
+        try { output = action.getResponseOutputStream(); }
         catch (IOException ex) { ServletOps.errorOccurred(ex); output = null; }
 
         Lang lang = RDFLanguages.contentTypeToLang(mediaType.getContentTypeStr());
@@ -85,11 +85,11 @@ public class GSP_R extends GSP_Base {
     }
 
     protected void execGetGSP(HttpAction action) {
-        ActionLib.setCommonHeaders(action.response);
+        ActionLib.setCommonHeaders(action);
         MediaType mediaType = ActionLib.contentNegotationRDF(action);
 
         ServletOutputStream output;
-        try { output = action.response.getOutputStream(); }
+        try { output = action.getResponseOutputStream(); }
         catch (IOException ex) { ServletOps.errorOccurred(ex); output = null; }
 
         Lang lang = RDFLanguages.contentTypeToLang(mediaType.getContentTypeStr());
@@ -129,8 +129,8 @@ public class GSP_R extends GSP_Base {
 
     @Override
     protected void doOptions(HttpAction action) {
-        ActionLib.setCommonHeadersForOptions(action.response);
-        action.response.setHeader(HttpNames.hAllow, "GET,HEAD,OPTIONS");
+        ActionLib.setCommonHeadersForOptions(action);
+        action.setResponseHeader(HttpNames.hAllow, "GET,HEAD,OPTIONS");
         ServletOps.success(action);
     }
 
@@ -143,7 +143,7 @@ public class GSP_R extends GSP_Base {
     }
 
     protected void execHeadQuads(HttpAction action) {
-        ActionLib.setCommonHeaders(action.response);
+        ActionLib.setCommonHeaders(action);
         MediaType mediaType = ActionLib.contentNegotationQuads(action);
         if ( action.verbose )
             action.log.info(format("[%d]   Head: Content-Type=%s", action.id, mediaType.getContentTypeStr()));
@@ -151,7 +151,7 @@ public class GSP_R extends GSP_Base {
     }
 
     protected void execHeadGSP(HttpAction action) {
-        ActionLib.setCommonHeaders(action.response);
+        ActionLib.setCommonHeaders(action);
         MediaType mediaType = ActionLib.contentNegotationRDF(action);
         if ( action.verbose )
             action.log.info(format("[%d]   Head: Content-Type=%s", action.id, mediaType.getContentTypeStr()));
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_RW.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_RW.java
index e3bc21b..3124a8d 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_RW.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_RW.java
@@ -46,11 +46,11 @@ public class GSP_RW extends GSP_R {
 
     @Override
     protected void doOptions(HttpAction action) {
-        ActionLib.setCommonHeadersForOptions(action.response);
+        ActionLib.setCommonHeadersForOptions(action);
         if ( GSPLib.hasGSPParams(action) )
-            action.response.setHeader(HttpNames.hAllow, "GET,HEAD,OPTIONS,PUT,DELETE,POST");
+            action.setResponseHeader(HttpNames.hAllow, "GET,HEAD,OPTIONS,PUT,DELETE,POST");
         else
-            action.response.setHeader(HttpNames.hAllow, "GET,HEAD,OPTIONS,PUT,POST");
+            action.setResponseHeader(HttpNames.hAllow, "GET,HEAD,OPTIONS,PUT,POST");
         ServletOps.success(action);
     }
 
@@ -153,7 +153,7 @@ public class GSP_RW extends GSP_R {
             DatasetGraph dsg = decideDataset(action);
             GraphTarget target = determineTargetGSP(dsg, action);
             if ( action.log.isDebugEnabled() )
-                action.log.debug(action.request.getMethod().toUpperCase()+"->"+target);
+                action.log.debug(action.getRequestMethod().toUpperCase()+"->"+target);
             if ( target.isUnion() )
                 ServletOps.errorBadRequest("Can't delete the union graph");
             // Check URI.
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GraphTarget.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GraphTarget.java
index 5b16f67..6245653 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GraphTarget.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GraphTarget.java
@@ -55,8 +55,8 @@ public class GraphTarget {
 //        if ( ! dsg.isInTransaction() )
 //            ServletOps.errorOccurred("Internal error : No transaction");
 
-        boolean dftGraph = GSPLib.getOneOnly(action.request, HttpNames.paramGraphDefault) != null;
-        String uri = GSPLib.getOneOnly(action.request, HttpNames.paramGraph);
+        boolean dftGraph = GSPLib.getOneOnly(action.getRequest(), HttpNames.paramGraphDefault) != null;
+        String uri = GSPLib.getOneOnly(action.getRequest(), HttpNames.paramGraph);
 
         if ( !dftGraph && uri == null ) {
             // No params - direct naming?
@@ -64,8 +64,8 @@ public class GraphTarget {
                 ServletOps.errorBadRequest("Neither default graph nor named graph specified");
 
             // Direct naming.
-            String directName = action.request.getRequestURL().toString();
-            if ( action.request.getRequestURI().equals(action.getDatasetName()) )
+            String directName = action.getRequestRequestURL().toString();
+            if ( action.getRequestRequestURI().equals(action.getDatasetName()) )
                 // No name (should have been a quads operations).
                 ServletOps.errorBadRequest("Neither default graph nor named graph specified and no direct name");
             Node gn = NodeFactory.createURI(directName);
@@ -121,7 +121,7 @@ public class GraphTarget {
             return null;
         }
 
-        String baseStr = action.request.getRequestURL().toString();
+        String baseStr = action.getRequestRequestURL().toString();
         Endpoint ep = action.getEndpoint();
         if ( ! ep.isUnnamed() && baseStr.endsWith(ep.getName()) ) {
             // Remove endpoint name
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java
index 6e88e84..7e1f544 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java
@@ -22,9 +22,14 @@ import static org.apache.jena.query.TxnType.READ;
 import static org.apache.jena.query.TxnType.READ_PROMOTE;
 import static org.apache.jena.query.TxnType.WRITE;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -89,8 +94,8 @@ public class HttpAction
 
     // Cleared to archive:
     public Map <String, String> headers = new HashMap<>();
-    public HttpServletRequest request;
-    public HttpServletResponseTracker response;
+    private HttpServletRequest request;
+    private HttpServletResponseTracker response;
     private final String actionURI;
     private final String contextPath;
 
@@ -195,7 +200,8 @@ public class HttpAction
         return context;
     }
 
-    /** Return the authenticated user this {@code HttpAction}.
+    /**
+     * Return the authenticated user this {@code HttpAction}.
      * Return null for no authenticated user.
      */
     public String getUser() {
@@ -417,12 +423,6 @@ public class HttpAction
         this.finishTime = System.nanoTime();
     }
 
-    public String getMethod()                           { return request.getMethod(); }
-
-    public HttpServletRequest getRequest()              { return request; }
-
-    public HttpServletResponseTracker getResponse()     { return response; }
-
     /**
      * Return the recorded time taken in milliseconds. {@link #setStartTime} and
      * {@link #setFinishTime} must have been called.
@@ -443,4 +443,123 @@ public class HttpAction
     public String toString() {
         return request.getMethod()+" "+request.getRequestURL().toString();
     }
+
+    // ---- Request - response abstraction. 
+    
+    public String getMethod()                           { return request.getMethod(); }
+
+    public HttpServletRequest getRequest()              { return request; }
+    public HttpServletResponse getResponse()            { return response; }
+    
+    // ---- Request accessors
+    
+    public String getRequestParameter(String string) {
+        return request.getParameter(string);
+    }
+
+    public Enumeration<String> getRequestParameterNames() {
+        return request.getParameterNames();
+    }
+    
+    public String[] getRequestParameterValues(String name) {
+        return request.getParameterValues(name);
+    }
+    
+    public Map<String, String[]> getRequestParameterMap() {
+        return request.getParameterMap();
+    }
+
+    public String getRequestMethod() {
+        return request.getMethod();
+    }
+
+    public Enumeration<String> getRequestHeaderNames() {
+        return request.getHeaderNames();
+    }
+    
+    public String getRequestHeader(String name) {
+        return request.getHeader(name);
+    }
+    
+    public Enumeration<String> getRequestHeaders(String name) {
+        return request.getHeaders(name);
+    }
+
+    public String getRequestContentType() {
+        return request.getContentType();
+    }
+
+    public String getRequestCharacterEncoding() {
+        return request.getCharacterEncoding();
+    }
+
+    public int getRequestContentLength() {
+        return request.getContentLength();
+    }
+    
+    public long getRequestContentLengthLong() {
+        return request.getContentLengthLong();
+    }
+
+    public InputStream getRequestInputStream() throws IOException {
+        return request.getInputStream();
+    }
+
+    public String getRequestQueryString() {
+        return request.getQueryString();
+    }
+    
+    public String getRequestRequestURI() {
+        return request.getRequestURI();
+    }
+
+    public StringBuffer getRequestRequestURL() {
+        return request.getRequestURL();
+    }
+    
+    public String getRequestPathInfo() {
+        return request.getPathInfo();
+    }
+    
+    public String getRequestServletPath() {
+        return request.getServletPath();
+    }
+
+    public int getRequestLocalPort() {
+        return request.getLocalPort();
+    }
+    
+    // ---- Response setters
+
+    public void setResponseCharacterEncoding(String charset) {
+        response.setCharacterEncoding(charset);
+    }
+
+    public void setResponseContentType(String ct) {
+        response.setContentType(ct);
+    }
+
+    public void setResponseContentLength(int length) {
+        response.setContentLength(length);
+    }
+    
+    public void setResponseContentLengthLong(long length) {
+        response.setContentLengthLong(length);
+    }
+
+    public void setResponseHeader(String name, String value) {
+        response.setHeader(name, value);
+    }
+
+    public void setResponseStatus(int statusCode) {
+        response.setStatus(statusCode);
+    }
+
+    public ServletOutputStream getResponseOutputStream() throws IOException {
+        return response.getOutputStream();
+    }
+
+    public PrintWriter getResponseWriter() throws IOException {
+        return response.getWriter();
+    }
 }
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseDataset.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseDataset.java
index fb5ec3e..2ab3a87 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseDataset.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseDataset.java
@@ -24,8 +24,8 @@ import java.util.HashMap;
 import java.util.Map;
 
 import javax.servlet.ServletOutputStream;
+//import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 
 import org.apache.jena.atlas.web.MediaType;
 import org.apache.jena.fuseki.DEF;
@@ -35,7 +35,9 @@ import org.apache.jena.fuseki.system.FusekiNetLib;
 import org.apache.jena.query.Dataset;
 import org.apache.jena.query.DatasetFactory;
 import org.apache.jena.rdf.model.Model;
-import org.apache.jena.riot.*;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.RDFFormat;
+import org.apache.jena.riot.RDFLanguages;
 import org.apache.jena.shared.JenaException;
 import org.apache.jena.web.HttpSC;
 
@@ -74,8 +76,7 @@ public class ResponseDataset
     }
 
     public static void doResponseDataset(HttpAction action, Dataset dataset) {
-        HttpServletRequest request = action.request;
-        HttpServletResponse response = action.response;
+        HttpServletRequest request = action.getRequest();
 
         String mimeType = null;        // Header request type
 
@@ -116,7 +117,7 @@ public class ResponseDataset
 
         try {
             ServletOps.success(action);
-            ServletOutputStream out = response.getOutputStream();
+            ServletOutputStream out = action.getResponseOutputStream();
             try {
                 // Use the Content-Type from the content negotiation.
                 if ( RDFLanguages.isQuads(lang) )
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseJson.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseJson.java
index 22bc621..bdc516f 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseJson.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseJson.java
@@ -24,8 +24,6 @@ import java.io.IOException;
 import java.util.Iterator;
 
 import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.jena.atlas.json.JsonObject;
@@ -71,8 +69,8 @@ public class ResponseJson {
         };
 
         try {
-            String callback = ResponseOps.paramCallback(action.request);
-            ServletOutputStream out = action.response.getOutputStream();
+            String callback = ResponseOps.paramCallback(action.getRequest());
+            ServletOutputStream out = action.getResponseOutputStream();
 
             if ( callback != null ) {
                 callback = StringUtils.replaceChars(callback, "\r", "");
@@ -92,9 +90,9 @@ public class ResponseJson {
 
     private static void output(HttpAction action, String contentType, String charset, OutputContent proc) {
         try {
-            setHttpResponse(action.request, action.response, contentType, charset);
-            action.response.setStatus(HttpSC.OK_200);
-            ServletOutputStream out = action.response.getOutputStream();
+            setHttpResponse(action, contentType, charset);
+            action.setResponseStatus(HttpSC.OK_200);
+            ServletOutputStream out = action.getResponseOutputStream();
             try {
                 proc.output(out);
                 out.flush();
@@ -117,21 +115,16 @@ public class ResponseJson {
         // then the JSON callback closing details can't be added.
     }
 
-    public static void setHttpResponse(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String contentType,
-                                       String charset) {
+    public static void setHttpResponse(HttpAction action, String contentType, String charset) {
         // ---- Set up HTTP Response
         // Stop caching (not that ?queryString URLs are cached anyway)
-        if ( true ) {
-            httpResponse.setHeader("Cache-Control", "no-cache");
-            httpResponse.setHeader("Pragma", "no-cache");
-        }
+        ServletOps.setNoCache(action);
         // See: http://www.w3.org/International/O-HTTP-charset.html
         if ( contentType != null ) {
             if ( charset != null )
                 contentType = contentType + "; charset=" + charset;
             xlog.trace("Content-Type for response: " + contentType);
-            httpResponse.setContentType(contentType);
+            action.setResponseContentType(contentType);
         }
     }
-
 }
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseOps.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseOps.java
index 5cedac2..29aad7d 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseOps.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseOps.java
@@ -96,7 +96,7 @@ class ResponseOps {
             if ( charset != null && !isXML(contentType) )
                 contentType = contentType + "; charset=" + charset;
             action.log.trace("Content-Type for response: " + contentType);
-            action.response.setContentType(contentType);
+            action.setResponseContentType(contentType);
         }
     }
 
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseResultSet.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseResultSet.java
index 14c0721..a94645b 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseResultSet.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseResultSet.java
@@ -28,7 +28,6 @@ import java.util.Objects;
 
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 
 import org.apache.jena.atlas.web.AcceptList;
 import org.apache.jena.atlas.web.MediaType;
@@ -89,8 +88,7 @@ public class ResponseResultSet
     private static void doResponseResultSet$(HttpAction action,
                                              ResultSet resultSet, Boolean booleanResult,
                                              Prologue qPrologue, AcceptList contentTypeOffer) {
-        HttpServletRequest request = action.request;
-        HttpServletResponse response = action.response;
+        HttpServletRequest request = action.getRequest();
         long id = action.id;
 
         if ( resultSet == null && booleanResult == null ) {
@@ -165,7 +163,7 @@ public class ResponseResultSet
                 cxt.set(ResultSetWriterXML.xmlStylesheet, stylesheetURL);
         }
         if ( Objects.equals(serializationType, contentTypeResultsJSON) ) {
-            jsonCallback = ResponseOps.paramCallback(action.request);
+            jsonCallback = ResponseOps.paramCallback(action.getRequest());
         }
         if (Objects.equals(serializationType, WebContent.contentTypeResultsThrift) ) {
             if ( booleanResult != null )
@@ -221,7 +219,7 @@ public class ResponseResultSet
         try {
             ResponseOps.setHttpResponse(action, contentType, charset);
             ServletOps.success(action);
-            ServletOutputStream out = action.response.getOutputStream();
+            ServletOutputStream out = action.getResponseOutputStream();
             try {
                 proc.output(out);
                 out.flush();
@@ -229,7 +227,7 @@ public class ResponseResultSet
                 // Status code 200 may have already been sent.
                 // We can try to set the HTTP response code anyway.
                 // Breaking the results is the best we can do to indicate the timeout.
-                action.response.setStatus(HttpSC.BAD_REQUEST_400);
+                action.setResponseStatus(HttpSC.BAD_REQUEST_400);
                 action.log.info(format("[%d] Query Cancelled - results truncated (but 200 may have already been sent)", action.id));
                 out.println();
                 out.println("##  Query cancelled due to timeout during execution   ##");
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SHACL_Validation.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SHACL_Validation.java
index ccf27b3..858ddbb 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SHACL_Validation.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SHACL_Validation.java
@@ -55,7 +55,7 @@ public class SHACL_Validation extends BaseActionREST { //ActionREST {
         if ( lang == null )
             lang = RDFLanguages.TTL;
 
-        String targetNodeStr = action.getRequest().getParameter(HttpNames.paramTarget);
+        String targetNodeStr = action.getRequestParameter(HttpNames.paramTarget);
 
         action.beginRead();
         try {
@@ -81,7 +81,7 @@ public class SHACL_Validation extends BaseActionREST { //ActionREST {
             else
                 action.log.info(format("[%d] shacl: %d validation errors", action.id, report.getEntries().size()));
             report.getEntries().size();
-            action.response.setStatus(HttpSC.OK_200);
+            action.setResponseStatus(HttpSC.OK_200);
             ActionLib.graphResponse(action, report.getGraph(), lang);
         } finally {
             action.endRead();
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQLProtocol.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQLProtocol.java
index 8142225..c46d5bc 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQLProtocol.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQLProtocol.java
@@ -87,8 +87,8 @@ public class SPARQLProtocol {
     }
 
     public static DatasetDescription getProtocolDatasetDescription(HttpAction action) {
-        List<String> graphURLs = toStrList(action.request.getParameterValues(paramDefaultGraphURI));
-        List<String> namedGraphs = toStrList(action.request.getParameterValues(paramNamedGraphURI));
+        List<String> graphURLs = toStrList(action.getRequestParameterValues(paramDefaultGraphURI));
+        List<String> namedGraphs = toStrList(action.getRequestParameterValues(paramNamedGraphURI));
 
         graphURLs = removeEmptyValues(graphURLs);
         namedGraphs = removeEmptyValues(namedGraphs);
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQLQueryProcessor.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQLQueryProcessor.java
index 0ddb6ef..c771d93 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQLQueryProcessor.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQLQueryProcessor.java
@@ -68,7 +68,6 @@ public abstract class SPARQLQueryProcessor extends ActionService
 
     @Override
     public void execOptions(HttpAction action) {
-        ServletBase.setCommonHeadersForOptions(action.response);
         ActionLib.doOptionsGetPost(action);
         ServletOps.success(action);    }
 
@@ -109,7 +108,7 @@ public abstract class SPARQLQueryProcessor extends ActionService
      */
     @Override
     public void validate(HttpAction action) {
-        String method = action.request.getMethod().toUpperCase(Locale.ROOT);
+        String method = action.getRequestMethod().toUpperCase(Locale.ROOT);
 
         if ( HttpNames.METHOD_OPTIONS.equals(method) )
             return;
@@ -117,9 +116,9 @@ public abstract class SPARQLQueryProcessor extends ActionService
         if ( !HttpNames.METHOD_POST.equals(method) && !HttpNames.METHOD_GET.equals(method) )
             ServletOps.errorMethodNotAllowed("Not a GET or POST request");
 
-        if ( HttpNames.METHOD_GET.equals(method) && action.request.getQueryString() == null ) {
-            ServletOps.warning(action, "Service Description / SPARQL Query / " + action.request.getRequestURI());
-            ServletOps.errorNotFound("Service Description: " + action.request.getRequestURI());
+        if ( HttpNames.METHOD_GET.equals(method) && action.getRequestQueryString() == null ) {
+            ServletOps.warning(action, "Service Description / SPARQL Query / " + action.getRequestRequestURI());
+            ServletOps.errorNotFound("Service Description: " + action.getRequestRequestURI());
         }
 
         // Use of the dataset describing parameters is checked later.
@@ -145,7 +144,7 @@ public abstract class SPARQLQueryProcessor extends ActionService
      * @param params parameters in a collection of Strings
      */
     protected void validateParams(HttpAction action, Collection<String> params) {
-        HttpServletRequest request = action.request;
+        HttpServletRequest request = action.getRequest();
         ContentType ct = FusekiNetLib.getContentType(request);
         boolean mustHaveQueryParam = true;
         if ( ct != null ) {
@@ -193,7 +192,7 @@ public abstract class SPARQLQueryProcessor extends ActionService
     @Override
     public final void execute(HttpAction action) {
         // GET
-        if ( action.request.getMethod().equals(HttpNames.METHOD_GET) ) {
+        if ( action.getRequestMethod().equals(HttpNames.METHOD_GET) ) {
             executeWithParameter(action);
             return;
         }
@@ -218,14 +217,14 @@ public abstract class SPARQLQueryProcessor extends ActionService
     }
 
     protected void executeWithParameter(HttpAction action) {
-        String queryString = action.request.getParameter(paramQuery);
+        String queryString = action.getRequestParameter(paramQuery);
         execute(queryString, action);
     }
 
     protected void executeBody(HttpAction action) {
         String queryString = null;
         try {
-            InputStream input = action.request.getInputStream();
+            InputStream input = action.getRequestInputStream();
             queryString = IO.readWholeFileAsUTF8(input);
         } catch (IOException ex) {
             ServletOps.errorOccurred(ex);
@@ -367,8 +366,8 @@ public abstract class SPARQLQueryProcessor extends ActionService
     private void setAnyProtocolTimeouts(QueryExecution qExec, HttpAction action) {
         // The timeout string in the protocol is in seconds, not milliseconds.
         String desiredTimeoutStr = null;
-        String timeoutHeader = action.request.getHeader("Timeout");
-        String timeoutParameter = action.request.getParameter("timeout");
+        String timeoutHeader = action.getRequestHeader("Timeout");
+        String timeoutParameter = action.getRequestParameter("timeout");
         if ( timeoutHeader != null )
             desiredTimeoutStr = timeoutHeader;
         if ( timeoutParameter != null )
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Update.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Update.java
index 6aaac2d..308b74d 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Update.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Update.java
@@ -21,6 +21,7 @@ package org.apache.jena.fuseki.servlets;
 import static java.lang.String.format;
 import static org.apache.jena.fuseki.server.CounterName.UpdateExecErrors;
 import static org.apache.jena.fuseki.servlets.ActionExecLib.incCounter;
+import static org.apache.jena.fuseki.servlets.SPARQLProtocol.countParamOccurences;
 import static org.apache.jena.fuseki.servlets.SPARQLProtocol.messageForException;
 import static org.apache.jena.fuseki.servlets.SPARQLProtocol.messageForParseException;
 import static org.apache.jena.riot.WebContent.*;
@@ -75,8 +76,8 @@ public class SPARQL_Update extends ActionService
 
     @Override
     public void execOptions(HttpAction action) {
-        ServletBase.setCommonHeadersForOptions(action.response);
-        action.response.setHeader(HttpNames.hAllow, "POST,PATCH,OPTIONS");
+        ActionLib.setCommonHeadersForOptions(action);
+        action.setResponseHeader(HttpNames.hAllow, "POST,PATCH,OPTIONS");
         ServletOps.success(action);
     }
 
@@ -109,7 +110,7 @@ public class SPARQL_Update extends ActionService
             executeForm(action);
             return;
         }
-        ServletOps.error(HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "Bad content type: " + action.request.getContentType());
+        ServletOps.error(HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "Bad content type: " + action.getRequestContentType());
     }
 
     protected static List<String> paramsForm = Arrays.asList(paramRequest, paramUpdate,
@@ -118,12 +119,12 @@ public class SPARQL_Update extends ActionService
 
     @Override
     public void validate(HttpAction action) {
-        HttpServletRequest request = action.request;
+        //HttpServletRequest request = action.getRequest();
 
-        if ( HttpNames.METHOD_OPTIONS.equals(request.getMethod()) )
+        if ( HttpNames.METHOD_OPTIONS.equals(action.getRequestMethod()) )
             return;
 
-        if ( ! HttpNames.METHOD_POST.equalsIgnoreCase(request.getMethod()) )
+        if ( ! HttpNames.METHOD_POST.equalsIgnoreCase(action.getRequestMethod()) )
             ServletOps.errorMethodNotAllowed("SPARQL Update : use POST");
 
         ContentType ct = ActionLib.getContentType(action);
@@ -131,7 +132,7 @@ public class SPARQL_Update extends ActionService
             ct = ctSPARQLUpdate;
 
         if ( matchContentType(ctSPARQLUpdate, ct) ) {
-            String charset = request.getCharacterEncoding();
+            String charset = action.getRequestCharacterEncoding();
             if ( charset != null && !charset.equalsIgnoreCase(charsetUTF8) )
                 ServletOps.errorBadRequest("Bad charset: " + charset);
             validate(action, paramsPOST);
@@ -139,15 +140,15 @@ public class SPARQL_Update extends ActionService
         }
 
         if ( isHtmlForm(ct) ) {
-            int x = SPARQLProtocol.countParamOccurences(request, paramUpdate) + SPARQLProtocol.countParamOccurences(request, paramRequest);
+            int x = countParamOccurences(action.getRequest(), paramUpdate) + countParamOccurences(action.getRequest(), paramRequest);
             if ( x == 0 )
                 ServletOps.errorBadRequest("SPARQL Update: No 'update=' parameter");
             if ( x != 1 )
                 ServletOps.errorBadRequest("SPARQL Update: Multiple 'update=' parameters");
 
-            String requestStr = request.getParameter(paramUpdate);
+            String requestStr = action.getRequestParameter(paramUpdate);
             if ( requestStr == null )
-                requestStr = request.getParameter(paramRequest);
+                requestStr = action.getRequestParameter(paramRequest);
             if ( requestStr == null )
                 ServletOps.errorBadRequest("SPARQL Update: No update= in HTML form");
             validate(action, paramsForm);
@@ -159,7 +160,7 @@ public class SPARQL_Update extends ActionService
 
     protected void validate(HttpAction action, Collection<String> params) {
         if ( params != null ) {
-            Enumeration<String> en = action.request.getParameterNames();
+            Enumeration<String> en = action.getRequestParameterNames();
             for (; en.hasMoreElements(); ) {
                 String name = en.nextElement();
                 if ( !params.contains(name) )
@@ -170,7 +171,7 @@ public class SPARQL_Update extends ActionService
 
     private void executeBody(HttpAction action) {
         InputStream input = null;
-        try { input = action.request.getInputStream(); }
+        try { input = action.getRequestInputStream(); }
         catch (IOException ex) { ServletOps.errorOccurred(ex); }
 
         if ( action.verbose ) {
@@ -192,9 +193,9 @@ public class SPARQL_Update extends ActionService
     }
 
     private void executeForm(HttpAction action) {
-        String requestStr = action.request.getParameter(paramUpdate);
+        String requestStr = action.getRequestParameter(paramUpdate);
         if ( requestStr == null )
-            requestStr = action.request.getParameter(paramRequest);
+            requestStr = action.getRequestParameter(paramRequest);
 
         if ( action.verbose )
             action.log.info(format("[%d] Form update = \n%s", action.id, requestStr));
@@ -208,7 +209,7 @@ public class SPARQL_Update extends ActionService
     }
 
     protected void execute(HttpAction action, InputStream input) {
-        UsingList usingList = processProtocol(action.request);
+        UsingList usingList = processProtocol(action.getRequest());
 
         // If the dsg is transactional, then we can parse and execute the update in a streaming fashion.
         // If it isn't, we need to read the entire update request before performing any updates, because
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Upload.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Upload.java
index 046ff74..ef9dbca 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Upload.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Upload.java
@@ -58,8 +58,8 @@ public class SPARQL_Upload extends ActionService
 
     @Override
     public void execOptions(HttpAction action) {
-        ServletBase.setCommonHeadersForOptions(action.response);
-        action.response.setHeader(HttpNames.hAllow, "POST,PATCH,OPTIONS");
+        ActionLib.setCommonHeadersForOptions(action);
+        action.setResponseHeader(HttpNames.hAllow, "POST,PATCH,OPTIONS");
         ServletOps.success(action);
     }
 
@@ -71,16 +71,16 @@ public class SPARQL_Upload extends ActionService
     public void execute(HttpAction action) {
 
         // Only allows one file in the upload.
-        boolean isMultipart = ServletFileUpload.isMultipartContent(action.request);
+        boolean isMultipart = ServletFileUpload.isMultipartContent(action.getRequest());
         if ( ! isMultipart )
             ServletOps.error(HttpSC.BAD_REQUEST_400 , "Not a file upload");
 
         long count = upload(action, Fuseki.BaseUpload);
         ServletOps.success(action);
         try {
-            action.response.setContentType("text/html");
-            action.response.setStatus(HttpSC.OK_200);
-            PrintWriter out = action.response.getWriter();
+            action.setResponseContentType("text/html");
+            action.setResponseStatus(HttpSC.OK_200);
+            PrintWriter out = action.getResponseWriter();
             out.println("<html>");
             out.println("<head>");
             out.println("</head>");
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ServletOps.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ServletOps.java
index 813b370..0c28f1b 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ServletOps.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ServletOps.java
@@ -106,15 +106,15 @@ public class ServletOps {
 
     //
     public static void success(HttpAction action, int httpStatusCode) {
-        action.response.setStatus(httpStatusCode);
+        action.setResponseStatus(httpStatusCode);
     }
 
     public static void successPage(HttpAction action, String message) {
         try {
-            action.response.setContentType("text/html");
-            action.response.setCharacterEncoding(WebContent.charsetUTF8);
-            action.response.setStatus(HttpSC.OK_200);
-            PrintWriter out = action.response.getWriter();
+            action.setResponseContentType("text/html");
+            action.setResponseCharacterEncoding(WebContent.charsetUTF8);
+            action.setResponseStatus(HttpSC.OK_200);
+            PrintWriter out = action.getResponseWriter();
             out.println("<html>");
             out.println("<head>");
             out.println("</head>");
@@ -211,7 +211,7 @@ public class ServletOps {
     }
 
     public static void setNoCache(HttpAction action) {
-        setNoCache(action.response);
+        setNoCache(action.getResponse());
     }
 
     public static void setNoCache(HttpServletResponse response) {
@@ -250,11 +250,10 @@ public class ServletOps {
         JSON.write(bytesOut, jValue);
         byte[] bytes = bytesOut.toByteArray();
         try {
-            HttpServletResponse response = action.response;
-            ServletOutputStream out = response.getOutputStream();
-            response.setContentType(WebContent.contentTypeJSON);
-            response.setContentLength(bytes.length);
-            response.setCharacterEncoding(WebContent.charsetUTF8);
+            ServletOutputStream out = action.getResponseOutputStream();
+            action.setResponseContentType(WebContent.contentTypeJSON);
+            action.setResponseContentLength(bytes.length);
+            action.setResponseCharacterEncoding(WebContent.charsetUTF8);
             out.write(bytes);
             out.flush();
         } catch (IOException ex) { ServletOps.errorOccurred(ex); }
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/FusekiNetLib.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/FusekiNetLib.java
index 6e3ea91..96127be 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/FusekiNetLib.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/FusekiNetLib.java
@@ -59,7 +59,7 @@ public class FusekiNetLib {
      * @return ContentType
      */
     public static Lang getLangFromAction(HttpAction action, Lang dft) {
-        String contentTypeHeader = action.request.getContentType();
+        String contentTypeHeader = action.getRequestContentType();
         if ( contentTypeHeader == null )
             return dft;
         return RDFLanguages.contentTypeToLang(contentTypeHeader);
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/Upload.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/Upload.java
index 19cc672..e4d3111 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/Upload.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/Upload.java
@@ -68,13 +68,13 @@ public class Upload {
         }
         // Single graph (or quads) in body.
 
-        String base = ActionLib.wholeRequestURL(action.request);
+        String base = ActionLib.wholeRequestURL(action.getRequest());
         Lang lang = RDFLanguages.contentTypeToLang(ct.getContentTypeStr());
         if ( lang == null ) {
             ServletOps.errorBadRequest("Unknown content type for triples: " + ct);
             return null;
         }
-        long len = action.request.getContentLengthLong();
+        long len = action.getRequestContentLengthLong();
 
         StreamRDFCounting countingDest = StreamRDFLib.count(dest);
         try {
@@ -100,12 +100,12 @@ public class Upload {
      */
 
     public static UploadDetails fileUploadWorker(HttpAction action, StreamRDF dest) {
-        String base = ActionLib.wholeRequestURL(action.request);
+        String base = ActionLib.wholeRequestURL(action.getRequest());
         ServletFileUpload upload = new ServletFileUpload();
         StreamRDFCounting countingDest =  StreamRDFLib.count(dest);
 
         try {
-            FileItemIterator iter = upload.getItemIterator(action.request);
+            FileItemIterator iter = upload.getItemIterator(action.getRequest());
             while (iter.hasNext()) {
                 FileItemStream fileStream = iter.next();
                 if (fileStream.isFormField()) {
@@ -196,7 +196,7 @@ public class Upload {
         Lang lang = null;
 
         try {
-            FileItemIterator iter = upload.getItemIterator(action.request);
+            FileItemIterator iter = upload.getItemIterator(action.getRequest());
             while (iter.hasNext()) {
                 FileItemStream item = iter.next();
                 String fieldName = item.getFieldName();
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/spot/SpotTDB2.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/spot/SpotTDB2.java
index 5e16493..0ce9599 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/spot/SpotTDB2.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/spot/SpotTDB2.java
@@ -28,12 +28,12 @@ import java.util.List;
 
 import org.apache.jena.atlas.io.IO;
 import org.apache.jena.dboe.base.file.Location;
+import org.apache.jena.dboe.sys.IO_DB;
 import org.apache.jena.dboe.sys.Names;
 import org.apache.jena.tdb2.TDBException;
 import org.apache.jena.tdb2.params.StoreParams;
 import org.apache.jena.tdb2.params.StoreParamsCodec;
 import org.apache.jena.tdb2.sys.DatabaseOps;
-import org.apache.jena.tdb2.sys.IOX;
 import org.apache.jena.tdb2.sys.Util;
 
 class SpotTDB2 {
@@ -82,7 +82,7 @@ class SpotTDB2 {
             // Or TDB1?
             return ! SpotTDB1.isTDB1(location.getDirectoryPath());
         // Validate storage.
-        Location storageLocation = IOX.asLocation(db);
+        Location storageLocation = IO_DB.asLocation(db);
         return isTDB2_Storage(storageLocation);
     }
 
@@ -117,7 +117,7 @@ class SpotTDB2 {
     /** Return the current active database area within a database directory. */
     private static Path storageDir(Location location) {
         // Database directory
-        Path path = IOX.asPath(location);
+        Path path = IO_DB.asPath(location);
         // Storage directory in database directory.
         Path db = findLocation(path, DatabaseOps.dbPrefix);
         return db;
@@ -127,7 +127,7 @@ class SpotTDB2 {
         if ( ! Files.exists(directory) )
             return null;
         // In-order, low to high.
-        List<Path> maybe = IOX.scanForDirByPattern(directory, namebase, DatabaseOps.SEP);
+        List<Path> maybe = IO_DB.scanForDirByPattern(directory, namebase, DatabaseOps.SEP);
         return Util.getLastOrNull(maybe);
     }
 
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/CustomTestService.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/CustomTestService.java
index 6ff9d9d..a7b8cdb 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/CustomTestService.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/CustomTestService.java
@@ -32,10 +32,10 @@ public class CustomTestService extends ActionREST {
 
     @Override
     protected void doGet(HttpAction action) {
-        action.response.setStatus(HttpSC.OK_200);
+        action.setResponseStatus(HttpSC.OK_200);
         try {
-            action.response.setContentType(WebContent.contentTypeTextPlain);
-            action.response.getOutputStream().println("    ** Hello world (GET) **");
+            action.setResponseContentType(WebContent.contentTypeTextPlain);
+            action.getResponseOutputStream().println("    ** Hello world (GET) **");
         }
         catch (IOException e) {
             e.printStackTrace();
@@ -44,16 +44,16 @@ public class CustomTestService extends ActionREST {
 
     @Override
     protected void doHead(HttpAction action) {
-        action.response.setStatus(HttpSC.OK_200);
-        action.response.setContentType(WebContent.contentTypeTextPlain);
+        action.setResponseStatus(HttpSC.OK_200);
+        action.setResponseContentType(WebContent.contentTypeTextPlain);
     }
 
     @Override
     protected void doPost(HttpAction action) {
-        action.response.setStatus(HttpSC.OK_200);
+        action.setResponseStatus(HttpSC.OK_200);
         try {
-            action.response.setContentType(WebContent.contentTypeTextPlain);
-            action.response.getOutputStream().println("    ** Hello world (POST) **");
+            action.setResponseContentType(WebContent.contentTypeTextPlain);
+            action.getResponseOutputStream().println("    ** Hello world (POST) **");
         }
         catch (IOException e) {
             e.printStackTrace();
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestFusekiCustomOperation.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestFusekiCustomOperation.java
index 84eb8c8..5b5ccfe 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestFusekiCustomOperation.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestFusekiCustomOperation.java
@@ -58,10 +58,10 @@ public class TestFusekiCustomOperation {
         new CustomTestService() {
         @Override
         protected void doGet(HttpAction action) {
-            action.response.setStatus(HttpSC.OK_200);
+            action.setResponseStatus(HttpSC.OK_200);
             try {
-                action.response.setContentType(WebContent.contentTypeTextPlain);
-                action.response.getOutputStream().print(customHandlerBodyGet);
+                action.setResponseContentType(WebContent.contentTypeTextPlain);
+                action.getResponseOutputStream().print(customHandlerBodyGet);
             } catch (IOException e) {
                 e.printStackTrace();
             }
@@ -69,16 +69,16 @@ public class TestFusekiCustomOperation {
 
         @Override
         protected void doHead(HttpAction action) {
-            action.response.setStatus(HttpSC.OK_200);
-            action.response.setContentType(WebContent.contentTypeTextPlain);
+            action.setResponseStatus(HttpSC.OK_200);
+            action.setResponseContentType(WebContent.contentTypeTextPlain);
         }
 
         @Override
         protected void doPost(HttpAction action) {
-            action.response.setStatus(HttpSC.OK_200);
+            action.setResponseStatus(HttpSC.OK_200);
             try {
-                action.response.setContentType(WebContent.contentTypeTextPlain);
-                action.response.getOutputStream().print(customHandlerBodyPost);
+                action.setResponseContentType(WebContent.contentTypeTextPlain);
+                action.getResponseOutputStream().print(customHandlerBodyPost);
             } catch (IOException e) {
                 e.printStackTrace();
             }
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/DemoService.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/DemoService.java
index 08b390c..b83273b 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/DemoService.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/DemoService.java
@@ -35,10 +35,10 @@ public class DemoService extends ActionREST {
 
     @Override
     protected void doGet(HttpAction action) {
-        action.response.setStatus(HttpSC.OK_200);
+        action.setResponseStatus(HttpSC.OK_200);
         try {
-            action.response.setContentType(WebContent.contentTypeTextPlain);
-            action.response.getOutputStream().println("    ** Hello world (GET) **");
+            action.setResponseContentType(WebContent.contentTypeTextPlain);
+            action.getResponseOutputStream().println("    ** Hello world (GET) **");
         }
         catch (IOException e) {
             e.printStackTrace();
@@ -47,16 +47,16 @@ public class DemoService extends ActionREST {
 
     @Override
     protected void doHead(HttpAction action) {
-        action.response.setStatus(HttpSC.OK_200);
-        action.response.setContentType(WebContent.contentTypeTextPlain);
+        action.setResponseStatus(HttpSC.OK_200);
+        action.setResponseContentType(WebContent.contentTypeTextPlain);
     }
 
     @Override
     protected void doPost(HttpAction action) {
-        action.response.setStatus(HttpSC.OK_200);
+        action.setResponseStatus(HttpSC.OK_200);
         try {
-            action.response.setContentType(WebContent.contentTypeTextPlain);
-            action.response.getOutputStream().println("    ** Hello world (POST) **");
+            action.setResponseContentType(WebContent.contentTypeTextPlain);
+            action.getResponseOutputStream().println("    ** Hello world (POST) **");
         }
         catch (IOException e) {
             e.printStackTrace();
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/InitFusekiCustomOperation.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/InitFusekiCustomOperation.java
index 0302597..7cf0713 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/InitFusekiCustomOperation.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/InitFusekiCustomOperation.java
@@ -74,10 +74,10 @@ public class InitFusekiCustomOperation implements JenaSubsystemLifecycle {
 
         @Override
         public void execute(HttpAction action) {
-            action.response.setStatus(HttpSC.OK_200);
-            action.response.setContentType(WebContent.contentTypeTextPlain);
+            action.setResponseStatus(HttpSC.OK_200);
+            action.setResponseContentType(WebContent.contentTypeTextPlain);
             try {
-                action.response.getOutputStream().print("** GET ** "+DateTimeUtils.nowAsXSDDateTimeString());
+                action.getResponseOutputStream().print("** GET ** "+DateTimeUtils.nowAsXSDDateTimeString());
             } catch (IOException e) {
                 throw new FusekiException(e);
             }
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java
index 97c170c..3e67c25 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java
@@ -57,7 +57,7 @@ public class ActionBackupList extends ActionCtl {
     @Override
     public void execute(HttpAction action) {
         JsonValue result = description(action);
-        ServletOps.setNoCache(action.response);
+        ServletOps.setNoCache(action);
         ServletOps.sendJsonReponse(action, result);
     }
 
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
index 7ecd9b2..f57d95a 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
@@ -127,7 +127,7 @@ public class ActionDatasets extends ActionContainerItem {
 
         ContentType ct = ActionLib.getContentType(action);
 
-        boolean hasParams = action.request.getParameterNames().hasMoreElements();
+        boolean hasParams = action.getRequestParameterNames().hasMoreElements();
 
         if ( ct == null && ! hasParams )
             ServletOps.errorBadRequest("Bad request - Content-Type or both parameters dbName and dbType required");
@@ -223,7 +223,7 @@ public class ActionDatasets extends ActionContainerItem {
                 FmtLog.warn(action.log, "Inconsistent names: datasetPath = %s; DataAccessPoint name = %s", datasetPath, dataAccessPoint);
 
             action.getDataAccessPointRegistry().register(dataAccessPoint);
-            action.getResponse().setContentType(WebContent.contentTypeTextPlain);
+            action.setResponseContentType(WebContent.contentTypeTextPlain);
             ServletOps.success(action);
             system.commit();
             committed = true;
@@ -297,7 +297,7 @@ public class ActionDatasets extends ActionContainerItem {
             // If not set explicitly, take from DataAccessPoint
             dSrv = action.getDataAccessPoint().getDataService();
 
-        String s = action.request.getParameter("state");
+        String s = action.getRequestParameter("state");
         if ( s == null || s.isEmpty() )
             ServletOps.errorBadRequest("No state change given");
 
@@ -454,9 +454,9 @@ public class ActionDatasets extends ActionContainerItem {
     }
 
     private static void assemblerFromForm(HttpAction action, StreamRDF dest) {
-        String x = action.getRequest().getQueryString();
-        String dbType = action.getRequest().getParameter(paramDatasetType);
-        String dbName = action.getRequest().getParameter(paramDatasetName);
+        String x = action.getRequestQueryString();
+        String dbType = action.getRequestParameter(paramDatasetType);
+        String dbName = action.getRequestParameter(paramDatasetName);
         if ( StringUtils.isBlank(dbType) || StringUtils.isBlank(dbName) )
             ServletOps.errorBadRequest("Received HTML form.  Both parameters 'dbName' and 'dbType' required");
 
@@ -536,7 +536,7 @@ public class ActionDatasets extends ActionContainerItem {
     // TODO Merge with Upload.incomingData
 
     private static void bodyAsGraph(HttpAction action, StreamRDF dest) {
-        HttpServletRequest request = action.request;
+        HttpServletRequest request = action.getRequest();
         String base = ActionLib.wholeRequestURL(request);
         ContentType ct = FusekiNetLib.getContentType(request);
         Lang lang = RDFLanguages.contentTypeToLang(ct.getContentTypeStr());
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionLogs.java b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionLogs.java
index 0f346c3..6a79343 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionLogs.java
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionLogs.java
@@ -24,7 +24,6 @@ import static org.apache.jena.riot.WebContent.contentTypeTextPlain;
 import java.io.IOException;
 
 import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletResponse;
 
 import org.apache.jena.fuseki.ctl.ActionCtl;
 import org.apache.jena.fuseki.servlets.HttpAction;
@@ -45,10 +44,9 @@ public class ActionLogs extends ActionCtl
     @Override
     public void execute(HttpAction action) {
         try {
-            HttpServletResponse response = action.response;
-            ServletOutputStream out = response.getOutputStream();
-            response.setContentType(contentTypeTextPlain);
-            response.setCharacterEncoding(charsetUTF8);
+            ServletOutputStream out = action.getResponseOutputStream();
+            action.setResponseContentType(contentTypeTextPlain);
+            action.setResponseCharacterEncoding(charsetUTF8);
             out.println("Not implemented yet");
             out.println();
             out.flush();
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionServerStatus.java b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionServerStatus.java
index 4d3ce5c..532d3b6 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionServerStatus.java
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionServerStatus.java
@@ -65,13 +65,13 @@ public class ActionServerStatus extends ActionCtl
     }
 
     private void description(HttpAction action) throws IOException {
-        ServletOutputStream out = action.response.getOutputStream();
-        action.response.setContentType(contentTypeJSON);
-        action.response.setCharacterEncoding(charsetUTF8);
+        ServletOutputStream out = action.getResponseOutputStream();
+        action.setResponseContentType(contentTypeJSON);
+        action.setResponseCharacterEncoding(charsetUTF8);
 
         JsonBuilder builder = new JsonBuilder();
         builder.startObject();
-        describeServer(builder, action.request.getLocalPort());
+        describeServer(builder, action.getRequestLocalPort());
         describeDatasets(builder, action.getDataAccessPointRegistry());
         builder.finishObject();