Added API versioning backwards compability and tests.

Change-Id: I8a7b512bea67e07e449074a4d04c257b65ae1454
diff --git a/core/Changes b/core/Changes
index 0a2d333..1541f93 100644
--- a/core/Changes
+++ b/core/Changes
@@ -1,6 +1,9 @@
 version 0.61.1
 28/08/2018
     - Added API URL versioning (margaretha)
+30/08/2018
+   - Added backwards compability for URL versioning (margaretha)
+   - Updated API version filter (margaretha)
 
 version 0.61.0
 13/08/2018
diff --git a/core/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java b/core/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
index 0a80e90..761911d 100644
--- a/core/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
+++ b/core/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
@@ -5,7 +5,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -14,7 +13,7 @@
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-//import org.apache.logging.log4j.PropertyConfigurator;
+// import org.apache.logging.log4j.PropertyConfigurator;
 
 import de.ids_mannheim.korap.util.KrillProperties;
 import de.ids_mannheim.korap.utils.TimeUtils;
@@ -81,13 +80,13 @@
     private String baseURL;
     private Properties properties;
 
-    private Set<String> version;
-    
+    private Set<String> supportedVersions;
+    private String currentVersion;
+
     // deprec?!
     private final BACKENDS DEFAULT_ENGINE = BACKENDS.LUCENE;
 
-    public KustvaktConfiguration (Properties properties)
-            throws Exception {
+    public KustvaktConfiguration (Properties properties) throws Exception {
         load(properties);
         KrillProperties.setProp(properties);
     }
@@ -100,13 +99,15 @@
      * @throws Exception
      */
     protected void load (Properties properties) throws Exception {
-        String version = properties.getProperty("supported.api.version", "");
-        if (version.isEmpty()){
-            throw new IllegalArgumentException("supported.api.version must be set in the .conf file");
+        currentVersion = properties.getProperty("current.api.version", "v1.0");
+        String supportedVersions =
+                properties.getProperty("supported.api.version", "");
+        if (supportedVersions.isEmpty()){
+            supportedVersions = currentVersion;
         }
-        this.version = Arrays.stream(version.split(" ")).collect(Collectors.toSet());
-        
-        
+        this.supportedVersions = Arrays.stream(supportedVersions.split(" "))
+                .collect(Collectors.toSet());
+
         baseURL = properties.getProperty("kustvakt.base.url", "/api/*");
         maxhits = new Integer(properties.getProperty("maxhits", "50000"));
         returnhits = new Integer(properties.getProperty("returnhits", "50000"));
@@ -176,15 +177,13 @@
     // this.load(props);
     // }
 
-
     /**
      * properties can be overloaded after spring init
      * 
      * @param stream
-     * @throws Exception 
+     * @throws Exception
      */
-    public void setPropertiesAsStream (InputStream stream)
-            throws Exception {
+    public void setPropertiesAsStream (InputStream stream) throws Exception {
         try {
 
             Properties p = new Properties();
@@ -197,7 +196,6 @@
 
     }
 
-
     public BACKENDS chooseBackend (String value) {
         if (value == null || value.equals("null"))
             return DEFAULT_ENGINE;
@@ -205,57 +203,56 @@
             return Enum.valueOf(BACKENDS.class, value.toUpperCase());
     }
 
-
-
     public static void loadLogger () {
-//        InputStream stream = ConfigLoader.loadConfigStream("log4j.properties");
-//        PropertyConfigurator.configure(stream);
+        // InputStream stream =
+        // ConfigLoader.loadConfigStream("log4j.properties");
+        // PropertyConfigurator.configure(stream);
         jlog.info("Done loading logging framework Log4j!");
     }
 
+    // @Deprecated
+    // public static void loadLog4jLogger () {
+    // /** loadSubTypes log4j configuration file programmatically */
+    // Properties log4j = new Properties();
+    // try {
+    // File f = new File(System.getProperty("user.dir"),
+    // "log4j.properties");
+    // if (f.exists()) {
+    // log4j.load(new FileInputStream(f));
+    // PropertyConfigurator.configure(log4j);
+    // jlog.info(
+    // "using local logging properties file ({}) to configure logging
+    // system",
+    // "./log4j.properties");
+    // return;
+    // }
+    // }
+    // catch (Exception e) {
+    // // do nothing
+    // }
+    // loadClassLogger();
+    // }
 
-
-//    @Deprecated
-//    public static void loadLog4jLogger () {
-//        /** loadSubTypes log4j configuration file programmatically */
-//        Properties log4j = new Properties();
-//        try {
-//            File f = new File(System.getProperty("user.dir"),
-//                    "log4j.properties");
-//            if (f.exists()) {
-//                log4j.load(new FileInputStream(f));
-//                PropertyConfigurator.configure(log4j);
-//                jlog.info(
-//                        "using local logging properties file ({}) to configure logging system",
-//                        "./log4j.properties");
-//                return;
-//            }
-//        }
-//        catch (Exception e) {
-//            // do nothing
-//        }
-//        loadClassLogger();
-//    }
-
-
-//    @Deprecated
-//    private static void loadClassLogger () {
-//        Properties log4j = new Properties();
-//        jlog.info(
-//                "using class path logging properties file to configure logging system");
-//
-//        try {
-//            log4j.load(KustvaktConfiguration.class.getClassLoader()
-//                    .getResourceAsStream("log4j.properties"));
-//        }
-//        catch (IOException e) {
-//            // do nothing
-//        }
-//
-//        PropertyConfigurator.configure(log4j);
-//        jlog.warn(
-//                "No logger properties detected. Using default logger properties");
-//    }
+    // @Deprecated
+    // private static void loadClassLogger () {
+    // Properties log4j = new Properties();
+    // jlog.info(
+    // "using class path logging properties file to configure logging
+    // system");
+    //
+    // try {
+    // log4j.load(KustvaktConfiguration.class.getClassLoader()
+    // .getResourceAsStream("log4j.properties"));
+    // }
+    // catch (IOException e) {
+    // // do nothing
+    // }
+    //
+    // PropertyConfigurator.configure(log4j);
+    // jlog.warn(
+    // "No logger properties detected. Using default logger
+    // properties");
+    // }
 
     public enum BACKENDS {
         NEO4J, LUCENE
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/APIVersionFilter.java b/core/src/main/java/de/ids_mannheim/korap/web/APIVersionFilter.java
index 886e475..0a36153 100644
--- a/core/src/main/java/de/ids_mannheim/korap/web/APIVersionFilter.java
+++ b/core/src/main/java/de/ids_mannheim/korap/web/APIVersionFilter.java
@@ -8,28 +8,27 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import com.sun.jersey.api.NotFoundException;
 import com.sun.jersey.spi.container.ContainerRequest;
 import com.sun.jersey.spi.container.ContainerRequestFilter;
 import com.sun.jersey.spi.container.ContainerResponseFilter;
 import com.sun.jersey.spi.container.ResourceFilter;
 
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.exceptions.StatusCodes;
 
-/** Checks API version in URL path. 
+/**
+ * Checks API version in URL path.
  * 
  * @author margaretha
  *
  */
 @Component
 @Provider
-public class APIVersionFilter implements ContainerRequestFilter, ResourceFilter {
+public class APIVersionFilter
+        implements ContainerRequestFilter, ResourceFilter {
 
     @Autowired
     private KustvaktConfiguration config;
-    @Autowired
-    private CoreResponseHandler kustvaktResponseHandler;
 
     @Override
     public ContainerRequestFilter getRequestFilter () {
@@ -46,10 +45,12 @@
         List<PathSegment> pathSegments = request.getPathSegments();
         String version = pathSegments.get(0).getPath();
 
-        if (!config.getVersion().contains(version)) {
-            throw kustvaktResponseHandler.throwit(
-                    new KustvaktException(StatusCodes.UNSUPPORTED_API_VERSION,
-                            "API " + version + " is unsupported.", version));
+        if (!config.getSupportedVersions().contains(version)) {
+            throw new NotFoundException(request.getRequestUri());
+            // throw kustvaktResponseHandler.throwit(
+            // new
+            // KustvaktException(StatusCodes.UNSUPPORTED_API_VERSION,
+            // "API " + version + " is unsupported.", version));
         }
         return request;
     }
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/utils/NotFoundMapper.java b/core/src/main/java/de/ids_mannheim/korap/web/utils/NotFoundMapper.java
new file mode 100644
index 0000000..7f5db5c
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/web/utils/NotFoundMapper.java
@@ -0,0 +1,65 @@
+package de.ids_mannheim.korap.web.utils;
+
+import java.net.URI;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.eclipse.jetty.http.HttpStatus;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.sun.jersey.api.NotFoundException;
+
+import de.ids_mannheim.korap.config.KustvaktConfiguration;
+
+@Component
+@Provider
+public class NotFoundMapper implements ExceptionMapper<NotFoundException> {
+
+    private static Logger jlog =
+            LogManager.getLogger(NotFoundMapper.class);
+    public static final Pattern VERSION_PATTERN =
+            Pattern.compile("/(v[0-9][^/]*)(/.*)");
+
+    @Autowired
+    private KustvaktConfiguration config;
+
+    @Override
+    public Response toResponse (NotFoundException exception) {
+        URI notFoundUri = exception.getNotFoundUri();
+
+        String path = notFoundUri.getPath();
+        String baseUrl = config.getBaseURL();
+        baseUrl = baseUrl.substring(0, baseUrl.length() - 2);
+
+        if (path.startsWith(baseUrl)) {
+            path = path.substring(baseUrl.length(), path.length());
+            Matcher matcher = VERSION_PATTERN.matcher(path);
+            if (!matcher.matches()) {
+                path = baseUrl + "/" + config.getCurrentVersion() + path;
+                URI redirectUri = UriBuilder.fromUri(notFoundUri)
+                        .replacePath(path).build();
+                jlog.debug("REDIRECT: "+redirectUri.toString());
+                return Response.status(HttpStatus.PERMANENT_REDIRECT_308)
+                        .location(redirectUri).build();
+            }
+            else if (!matcher.group(1).equals(config.getCurrentVersion())){
+                path = baseUrl + "/" + config.getCurrentVersion()
+                        + matcher.group(2);
+                URI redirectUri = UriBuilder.fromUri(notFoundUri)
+                        .replacePath(path).build();
+                jlog.debug("REDIRECT replace: "+ redirectUri.toString());
+                return Response.status(HttpStatus.PERMANENT_REDIRECT_308)
+                        .location(redirectUri).build();
+            }
+        }
+        return Response.status(HttpStatus.NOT_FOUND_404).build();
+    }
+}
diff --git a/full/Changes b/full/Changes
index 8013fad..e92fade 100644
--- a/full/Changes
+++ b/full/Changes
@@ -3,7 +3,10 @@
     - Added API URL versioning (margaretha) 
     - Deactivated IdRewrite (margaretha)
     - Fixed kustvakt controller (margaretha)
-
+30/08/2018
+    - Fixed root packages & added api version properties in kustvakt.conf (margaretha)
+    - Fixed versioning in SearchController (margaretha)
+    - Added API versioning tests (margaretha)
 
 # version 0.61.0
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/server/KustvaktServer.java b/full/src/main/java/de/ids_mannheim/korap/server/KustvaktServer.java
index 01da674..5e97ea1 100644
--- a/full/src/main/java/de/ids_mannheim/korap/server/KustvaktServer.java
+++ b/full/src/main/java/de/ids_mannheim/korap/server/KustvaktServer.java
@@ -42,8 +42,7 @@
         if (kargs.getSpringConfig() == null){
             kargs.setSpringConfig("default-config.xml");
         }
-        rootPackages = "de.ids_mannheim.korap.web.utils;"
-                + "de.ids_mannheim.korap.web.service.full";
+        rootPackages = "de.ids_mannheim.korap.web;";
         server.start();
     }
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/SearchService.java b/full/src/main/java/de/ids_mannheim/korap/service/SearchService.java
index 1aea369..e1c8ae8 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/SearchService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/SearchService.java
@@ -56,6 +56,7 @@
         this.graphDBhandler = new ClientsHandler(builder.build());
     }
 
+    @SuppressWarnings("unchecked")
     public String serializeQuery (String q, String ql, String v, String cq,
             Integer pageIndex, Integer startPage, Integer pageLength,
             String context, Boolean cutoff) {
@@ -91,6 +92,7 @@
         return searchKrill.search(jsonld);
     }
 
+    @SuppressWarnings("unchecked")
     public String search (String engine, String username, HttpHeaders headers,
             String q, String ql, String v, String cq, Integer pageIndex,
             Integer pageInteger, String ctx, Integer pageLength, Boolean cutoff)
@@ -123,7 +125,7 @@
         else {
             result = searchKrill.search(query);
         }
-        jlog.debug("Query result: " + result);
+//        jlog.debug("Query result: " + result);
         return result;
 
     }
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/KustvaktController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/KustvaktController.java
index 37792b6..230afe1 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/KustvaktController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/KustvaktController.java
@@ -38,7 +38,7 @@
         
         Map m = new HashMap();
         m.put("version", ServiceInfo.getInfo().getVersion());
-        m.put("supported_api_version(s)", config.getVersion());
+        m.put("supported_api_version(s)", config.getSupportedVersions());
         m.put("service_name", ServiceInfo.getInfo().getName());
         try {
             return Response.ok(JsonUtils.toJSON(m)).build();
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java
index a74c83a..41e5e2c 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java
@@ -43,7 +43,7 @@
  * 
  */
 @Controller
-@Path("/{version}/")
+@Path("/")
 @ResourceFilters({ APIVersionFilter.class, AuthenticationFilter.class,
         DemoUserFilter.class, PiwikFilter.class })
 @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
@@ -83,7 +83,7 @@
      */
     // ref query parameter removed!
     @GET
-    @Path("query")
+    @Path("{version}/query")
     public Response serializeQuery (@Context Locale locale,
             @Context SecurityContext securityContext, @QueryParam("q") String q,
             @QueryParam("ql") String ql, @QueryParam("v") String v,
@@ -108,7 +108,7 @@
     }
 
     @POST
-    @Path("search")
+    @Path("{version}/search")
     public Response searchPost (@Context SecurityContext context,
             @Context Locale locale, @QueryParam("engine") String engine,
             String jsonld) {
@@ -127,7 +127,7 @@
     }
 
     @GET
-    @Path("search")
+    @Path("{version}/search")
     public Response searchGet (@Context SecurityContext securityContext,
             @Context HttpHeaders headers, @Context Locale locale,
             @QueryParam("q") String q, @QueryParam("ql") String ql,
@@ -156,7 +156,7 @@
     }
 
     @GET
-    @Path("/corpus/{corpusId}/{docId}/{textId}/{matchId}/matchInfo")
+    @Path("{version}/corpus/{corpusId}/{docId}/{textId}/{matchId}/matchInfo")
     public Response getMatchInfo (@Context SecurityContext ctx,
             @Context HttpHeaders headers, @Context Locale locale,
             @PathParam("corpusId") String corpusId,
@@ -184,7 +184,7 @@
     // This is currently identical to LiteService#getMeta(),
     // but may need auth code to work following policies
     @GET
-    @Path("/corpus/{corpusId}/{docId}/{textId}")
+    @Path("{version}/corpus/{corpusId}/{docId}/{textId}")
     public Response getMetadata (@PathParam("corpusId") String corpusId,
             @PathParam("docId") String docId, @PathParam("textId") String textId
     // @QueryParam("fields") Set<String> fields
@@ -195,7 +195,7 @@
     }
 
     @POST
-    @Path("colloc")
+    @Path("{version}/colloc")
     public Response getCollocationBase (@QueryParam("q") String query) {
         String result;
         try {
diff --git a/full/src/main/resources/kustvakt.conf b/full/src/main/resources/kustvakt.conf
index 0a1ddc3..3932b82 100644
--- a/full/src/main/resources/kustvakt.conf
+++ b/full/src/main/resources/kustvakt.conf
@@ -12,8 +12,9 @@
 ldap.config = file-path-to-ldap-config
 
 # Kustvakt
+current.api.version = v1.0
 # multiple versions separated by space
-supported.api.version = v0.1 v1.0
+supported.api.version = v1.0
 
 ## server
 server.port=8089
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/ApiVersionTest.java b/full/src/test/java/de/ids_mannheim/korap/web/ApiVersionTest.java
new file mode 100644
index 0000000..b8ca799
--- /dev/null
+++ b/full/src/test/java/de/ids_mannheim/korap/web/ApiVersionTest.java
@@ -0,0 +1,39 @@
+package de.ids_mannheim.korap.web;
+
+import static org.junit.Assert.assertEquals;
+
+import java.net.URI;
+
+import javax.ws.rs.core.MediaType;
+
+import org.eclipse.jetty.http.HttpStatus;
+import org.junit.Test;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+import de.ids_mannheim.korap.config.SpringJerseyTest;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+
+public class ApiVersionTest extends SpringJerseyTest {
+
+    @Test
+    public void testSearchWithoutVersion () throws KustvaktException {
+        ClientResponse response = resource().path("api").path("search")
+                .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
+                .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+        assertEquals(HttpStatus.PERMANENT_REDIRECT_308, response.getStatus());
+        URI location = response.getLocation();
+        assertEquals("/api/v1.0/search", location.getPath());
+    }
+
+    @Test
+    public void testSearchWrongVersion () throws KustvaktException {
+        ClientResponse response = resource().path("api").path("v0.2")
+                .path("search").queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp").accept(MediaType.APPLICATION_JSON)
+                .get(ClientResponse.class);
+        assertEquals(HttpStatus.PERMANENT_REDIRECT_308, response.getStatus());
+        URI location = response.getLocation();
+        assertEquals("/api/v1.0/search", location.getPath());
+    }
+}
diff --git a/full/src/test/resources/kustvakt-test.conf b/full/src/test/resources/kustvakt-test.conf
index 304e649..9a522ba 100644
--- a/full/src/test/resources/kustvakt-test.conf
+++ b/full/src/test/resources/kustvakt-test.conf
@@ -12,6 +12,8 @@
 ldap.config = file-path-to-ldap-config
 
 # Kustvakt
+
+current.api.version = v1.0
 # multiple versions separated by space
 supported.api.version = v0.1 v1.0
 
diff --git a/lite/Changes b/lite/Changes
index 942779a..105e619 100644
--- a/lite/Changes
+++ b/lite/Changes
@@ -1,13 +1,16 @@
 version 0.61.0
-28/08/2018
-   - Added API URL versioning (margaretha)
-   
+30/08/2018
+   - Fixed root packages & added api version properties in kustvakt-lite.conf (margaretha)
+   - Added API versioning tests (margaretha)
+
 version 0.60.2
 05/07/2018
     - Added support for unrestricted corpus statistics (ndiewald)
     - Do not pass broken queries to Krill (diewald)
 27/08/2018
     - Added vc reference test (margaretha)
+28/08/2018
+   - Added API URL versioning (margaretha)
 
 version 0.60.1
 12/06/2018
diff --git a/lite/pom.xml b/lite/pom.xml
index 9e8ccaf..2e57372 100644
--- a/lite/pom.xml
+++ b/lite/pom.xml
@@ -3,7 +3,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>de.ids_mannheim.korap</groupId>
 	<artifactId>Kustvakt-lite</artifactId>
-	<version>0.60.2</version>
+	<version>0.61.0</version>
 	<properties>
 		<java.version>1.8</java.version>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
diff --git a/lite/src/main/java/de/ids_mannheim/korap/server/KustvaktLiteServer.java b/lite/src/main/java/de/ids_mannheim/korap/server/KustvaktLiteServer.java
index 66329ef..448d4f6 100644
--- a/lite/src/main/java/de/ids_mannheim/korap/server/KustvaktLiteServer.java
+++ b/lite/src/main/java/de/ids_mannheim/korap/server/KustvaktLiteServer.java
@@ -10,7 +10,6 @@
 
 public class KustvaktLiteServer extends KustvaktBaseServer {
 
-
     public static void main (String[] args) throws Exception {
         KustvaktLiteServer server = new KustvaktLiteServer();
         kargs = server.readAttributes(args);
@@ -20,20 +19,22 @@
         File f = new File("kustvakt-lite.conf");
         Properties properties = new Properties();
         InputStream in = null;
-        
-        if (!f.exists()){
-            in = KustvaktLiteServer.class.getClassLoader().getResourceAsStream("kustvakt-lite.conf");
+
+        if (!f.exists()) {
+            in = KustvaktLiteServer.class.getClassLoader()
+                    .getResourceAsStream("kustvakt-lite.conf");
         }
-        else{
+        else {
             in = new FileInputStream(f);
         }
-        
+
         properties.load(in);
         in.close();
         config = new KustvaktConfiguration(properties);
-        
+
         kargs.setSpringConfig("lite-config.xml");
-        rootPackages = "de.ids_mannheim.korap.web.service.lite";
+        rootPackages =
+                "de.ids_mannheim.korap.web";
 
         server.start();
     }
diff --git a/lite/src/main/java/de/ids_mannheim/korap/web/service/lite/LiteService.java b/lite/src/main/java/de/ids_mannheim/korap/web/service/lite/LiteService.java
index f5b648b..d268617 100644
--- a/lite/src/main/java/de/ids_mannheim/korap/web/service/lite/LiteService.java
+++ b/lite/src/main/java/de/ids_mannheim/korap/web/service/lite/LiteService.java
@@ -33,10 +33,10 @@
 import de.ids_mannheim.korap.query.serialize.QuerySerializer;
 import de.ids_mannheim.korap.resource.rewrite.RewriteHandler;
 import de.ids_mannheim.korap.utils.KoralCollectionQueryBuilder;
+import de.ids_mannheim.korap.web.APIVersionFilter;
 import de.ids_mannheim.korap.web.ClientsHandler;
 import de.ids_mannheim.korap.web.CoreResponseHandler;
 import de.ids_mannheim.korap.web.SearchKrill;
-import de.ids_mannheim.korap.web.APIVersionFilter;
 
 /**
  * @author hanl
@@ -50,7 +50,7 @@
  * - removed version from service paths
  * - altered service with path /search and method trace to path
  * /query and method get
- * - added API versioning
+ * - added API URL versioning
  * </pre>
  */
 @Controller
@@ -62,7 +62,7 @@
     private static Logger jlog = LogManager.getLogger(LiteService.class);
 
     @Autowired
-    CoreResponseHandler kustvaktResponseHandler;
+    private CoreResponseHandler kustvaktResponseHandler;
     @Autowired
     private SearchKrill searchKrill;
     private ClientsHandler graphDBhandler;
diff --git a/lite/src/main/resources/kustvakt-lite.conf b/lite/src/main/resources/kustvakt-lite.conf
index 79e2211..f0dd6b3 100644
--- a/lite/src/main/resources/kustvakt-lite.conf
+++ b/lite/src/main/resources/kustvakt-lite.conf
@@ -6,6 +6,15 @@
 krill.index.commit.auto = 500
 krill.index.relations.max = 100
 
+krill.namedVC=vc
+
+
+# Kustvakt
+
+current.api.version = v1.0
+# multiple versions separated by space
+supported.api.version = v1.0
+
 kustvakt.base.url=/api/*
 kustvakt.default.pos = tt
 kustvakt.default.lemma = tt
diff --git a/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteServiceTest.java b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteServiceTest.java
index 8212e84..3578b21 100644
--- a/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteServiceTest.java
+++ b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteServiceTest.java
@@ -8,9 +8,13 @@
 
 import java.io.IOException;
 import java.net.ServerSocket;
+import java.net.URI;
 import java.util.Iterator;
 import java.util.concurrent.ThreadLocalRandom;
 
+import javax.ws.rs.core.MediaType;
+
+import org.eclipse.jetty.http.HttpStatus;
 import org.junit.Test;
 import org.springframework.web.context.ContextLoaderListener;
 
@@ -41,7 +45,7 @@
  */
 public class LiteServiceTest extends JerseyTest{
 
-    public static final String API_VERSION = "v0.1";
+    public static final String API_VERSION = "v1.0";
     public static final String classPackage = "de.ids_mannheim.korap.web.service.lite";
 
     @Override
@@ -425,4 +429,25 @@
 		};
 		assertEquals(5, checkC);
 	};
+	
+    @Test
+    public void testSearchWithoutVersion () throws KustvaktException {
+        ClientResponse response = resource().path("api").path("search")
+                .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
+                .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+        assertEquals(HttpStatus.PERMANENT_REDIRECT_308, response.getStatus());
+        URI location = response.getLocation();
+        assertEquals("/api/v1.0/search", location.getPath());
+    }
+
+    @Test
+    public void testSearchWrongVersion () throws KustvaktException {
+        ClientResponse response = resource().path("api").path("v0.2")
+                .path("search").queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp").accept(MediaType.APPLICATION_JSON)
+                .get(ClientResponse.class);
+        assertEquals(HttpStatus.PERMANENT_REDIRECT_308, response.getStatus());
+        URI location = response.getLocation();
+        assertEquals("/api/v1.0/search", location.getPath());
+    }
 }