Integrated lite and full services and controllers in core.

Change-Id: I34914c89c2266fa02bee1a5b0522c46139b13966
diff --git a/lite/Changes b/lite/Changes
index 97abbec..31a61a9 100644
--- a/lite/Changes
+++ b/lite/Changes
@@ -1,3 +1,6 @@
+version 0.61.2
+   - Integrated lite and full services and controllers in core (margaretha)
+
 version 0.61.1
 22/10/2018
    - Updated spring and kustvakt-core versions (margaretha)
@@ -6,7 +9,7 @@
 07/11/2018
     - OpenJDK8u181-workaround (see Debian Bug report #911925; diewald)
 13/11/2018
-    - Added shutdown handler (margaretha)    
+    - Added shutdown handler (margaretha)
 
 version 0.61.0
 30/08/2018
diff --git a/lite/liteDB.sqlite b/lite/liteDB.sqlite
new file mode 100644
index 0000000..4342bb3
--- /dev/null
+++ b/lite/liteDB.sqlite
Binary files differ
diff --git a/lite/pom.xml b/lite/pom.xml
index 9394b19..6b9ae4f 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.61.1</version>
+	<version>0.61.2</version>
 	<properties>
 		<java.version>1.8</java.version>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -15,15 +15,6 @@
 		<resources>
 			<resource>
 				<directory>src/main/resources</directory>
-				<filtering>true</filtering>
-				<includes>
-					<include>**/*.info</include>
-					<include>**/*.xml</include>
-					<include>**/*.conf</include>
-					<include>**/*.kustvakt</include>
-					<include>**/*.properties</include>
-					<include>**/*.sql</include>
-				</includes>
 			</resource>
 		</resources>
 		<testResources>
@@ -148,17 +139,8 @@
 		<dependency>
 			<groupId>de.ids_mannheim.korap</groupId>
 			<artifactId>Kustvakt-core</artifactId>
-			<version>0.61.3</version>
+			<version>[0.61.3,)</version>
 		</dependency>
-		
-		<!-- Spring -->
-		<dependency>
-			<groupId>org.springframework</groupId>
-			<artifactId>spring-test</artifactId>
-			<version>${spring-framework.version}</version>
-			<scope>compile</scope>
-		</dependency>
-		
 		<!-- Jersey test framework -->
 		<dependency>
 			<groupId>com.sun.jersey.jersey-test-framework</groupId>
diff --git a/lite/src/main/java/de/ids_mannheim/de/init/LiteInitializatorImpl.java b/lite/src/main/java/de/ids_mannheim/de/init/LiteInitializatorImpl.java
new file mode 100644
index 0000000..b9229cd
--- /dev/null
+++ b/lite/src/main/java/de/ids_mannheim/de/init/LiteInitializatorImpl.java
@@ -0,0 +1,26 @@
+package de.ids_mannheim.de.init;
+
+import java.io.IOException;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import de.ids_mannheim.korap.annotation.AnnotationParser;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.util.QueryException;
+
+public class LiteInitializatorImpl implements Initializator {
+
+    @Autowired
+    private AnnotationParser annotationParser;
+    
+    @Override
+    public void init () throws IOException, QueryException, KustvaktException {
+        annotationParser.run();
+    }
+
+    @Override
+    public void initTest () throws IOException, KustvaktException {
+//        annotationParser.run();
+    }
+
+}
diff --git a/lite/src/main/java/de/ids_mannheim/korap/authentication/DummyAuthenticationManager.java b/lite/src/main/java/de/ids_mannheim/korap/authentication/DummyAuthenticationManager.java
new file mode 100644
index 0000000..22f1d12
--- /dev/null
+++ b/lite/src/main/java/de/ids_mannheim/korap/authentication/DummyAuthenticationManager.java
@@ -0,0 +1,138 @@
+package de.ids_mannheim.korap.authentication;
+
+import java.util.Map;
+
+import javax.ws.rs.core.HttpHeaders;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import de.ids_mannheim.korap.config.KustvaktConfiguration;
+import de.ids_mannheim.korap.constant.AuthenticationMethod;
+import de.ids_mannheim.korap.constant.TokenType;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.security.context.TokenContext;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.user.Userdata;
+import de.ids_mannheim.korap.utils.TimeUtils;
+
+public class DummyAuthenticationManager extends AuthenticationManager {
+
+    @Autowired
+    private KustvaktConfiguration config;
+
+    public DummyAuthenticationManager () {}
+    
+    @Override
+    public TokenContext getTokenContext (TokenType type, String token,
+            String host, String useragent) throws KustvaktException {
+        TokenContext c = new TokenContext();
+        c.setUsername("guest");
+        c.setHostAddress(host);
+        c.setUserAgent(useragent);
+        c.setExpirationTime(
+                TimeUtils.plusSeconds(config.getShortTokenTTL()).getMillis());
+        c.setTokenType(TokenType.BASIC);
+        c.setToken("dummyToken");
+        return c;
+    }
+
+    @Override
+    public User getUser (String username) throws KustvaktException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean isRegistered (String id) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public User authenticate (AuthenticationMethod method, String username,
+            String password, Map<String, Object> attributes)
+            throws KustvaktException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public TokenContext createTokenContext (User user, Map<String, Object> attr,
+            TokenType type) throws KustvaktException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void setAccessAndLocation (User user, HttpHeaders headers) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void logout (TokenContext context) throws KustvaktException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void lockAccount (User user) throws KustvaktException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public User createUserAccount (Map<String, Object> attributes,
+            boolean confirmation_required) throws KustvaktException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean deleteAccount (User user) throws KustvaktException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public <T extends Userdata> T getUserData (User user, Class<T> clazz)
+            throws KustvaktException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void updateUserData (Userdata data) throws KustvaktException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public Object[] validateResetPasswordRequest (String username, String email)
+            throws KustvaktException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void resetPassword (String uriFragment, String username,
+            String newPassphrase) throws KustvaktException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void confirmRegistration (String uriFragment, String username)
+            throws KustvaktException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public User getUser (String username, String method)
+            throws KustvaktException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git a/lite/src/main/java/de/ids_mannheim/korap/dao/DummyAdminDaoImpl.java b/lite/src/main/java/de/ids_mannheim/korap/dao/DummyAdminDaoImpl.java
new file mode 100644
index 0000000..0d31885
--- /dev/null
+++ b/lite/src/main/java/de/ids_mannheim/korap/dao/DummyAdminDaoImpl.java
@@ -0,0 +1,18 @@
+package de.ids_mannheim.korap.dao;
+
+import de.ids_mannheim.korap.user.User;
+
+public class DummyAdminDaoImpl implements AdminDao {
+
+    @Override
+    public void addAccount (User user) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean isAdmin (String userId) {
+        return false;
+    }
+
+}
diff --git a/lite/src/main/java/de/ids_mannheim/korap/oauth2/service/DummyOAuth2ScopeServiceImpl.java b/lite/src/main/java/de/ids_mannheim/korap/oauth2/service/DummyOAuth2ScopeServiceImpl.java
new file mode 100644
index 0000000..891dc12
--- /dev/null
+++ b/lite/src/main/java/de/ids_mannheim/korap/oauth2/service/DummyOAuth2ScopeServiceImpl.java
@@ -0,0 +1,15 @@
+package de.ids_mannheim.korap.oauth2.service;
+
+import de.ids_mannheim.korap.constant.OAuth2Scope;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.security.context.TokenContext;
+
+public class DummyOAuth2ScopeServiceImpl implements OAuth2ScopeService {
+
+      @Override
+    public void verifyScope (TokenContext context, OAuth2Scope requiredScope)
+            throws KustvaktException {
+        // TODO Auto-generated method stub
+
+    }
+}
diff --git a/lite/src/main/java/de/ids_mannheim/korap/server/KustvaktBaseServer.java b/lite/src/main/java/de/ids_mannheim/korap/server/KustvaktBaseServer.java
deleted file mode 100644
index 3786b11..0000000
--- a/lite/src/main/java/de/ids_mannheim/korap/server/KustvaktBaseServer.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package de.ids_mannheim.korap.server;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.UUID;
-
-import javax.servlet.ServletContextListener;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.lang.ArrayUtils;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.handler.HandlerList;
-import org.eclipse.jetty.server.handler.ShutdownHandler;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.springframework.web.context.ContextLoaderListener;
-
-import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
-
-import de.ids_mannheim.korap.config.KustvaktConfiguration;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * @author hanl
- * @date 01/06/2015
- */
-public abstract class KustvaktBaseServer {
-
-    protected static KustvaktConfiguration config;
-
-    protected static String rootPackages;
-    protected static KustvaktArgs kargs;
-
-    public KustvaktBaseServer () {}
-
-    protected KustvaktArgs readAttributes (String[] args) {
-        KustvaktArgs kargs = new KustvaktArgs();
-        for (int i = 0; i < args.length; i++) {
-            switch ((args[i])) {
-                case "--spring-config":
-                    kargs.setSpringConfig(args[i + 1]);
-                    break;
-                case "--port":
-                    kargs.setPort(Integer.valueOf(args[i + 1]));
-                    break;
-                case "--help":
-                    StringBuffer b = new StringBuffer();
-
-                    b.append("Parameter description: \n")
-                            .append("--spring-config  <Spring XML configuration filename in classpath>\n")
-                            .append("--port  <Server port number>\n")
-                            .append("--help : This help menu\n");
-                    System.out.println(b.toString());
-                    System.out.println();
-                    return (KustvaktArgs) null;
-            }
-        }
-        return kargs;
-    }
-
-    protected void start ()
-            throws KustvaktException, IOException, NoSuchAlgorithmException {
-
-        if (kargs.port == -1) {
-            kargs.setPort(config.getPort());
-        }
-
-        Server server = new Server();
-
-        ServletContextHandler contextHandler =
-                new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
-        contextHandler.setContextPath("/");
-        contextHandler.setInitParameter("contextConfigLocation",
-                "classpath:" + kargs.getSpringConfig());
-
-        ServletContextListener listener = new ContextLoaderListener();
-        contextHandler.addEventListener(listener);
-
-        ServletHolder servletHolder = new ServletHolder(new SpringServlet());
-        servletHolder.setInitParameter(
-                "com.sun.jersey.config.property.packages", rootPackages);
-        servletHolder.setInitParameter(
-                "com.sun.jersey.api.json.POJOMappingFeature", "true");
-        servletHolder.setInitOrder(1);
-        contextHandler.addServlet(servletHolder, config.getBaseURL());
-
-        ServerConnector connector = new ServerConnector(server);
-        connector.setPort(kargs.port);
-        connector.setIdleTimeout(60000);
-
-        String shutdownToken = createRandomCode();
-        ShutdownHandler shutdownHandler =
-                new ShutdownHandler(shutdownToken, true, true);
-
-        FileOutputStream fos = new FileOutputStream(new File("shutdownToken"));
-        OutputStreamWriter writer =
-                new OutputStreamWriter(fos, StandardCharsets.UTF_8.name());
-        writer.write(shutdownToken);
-        writer.flush();
-        writer.close();
-
-        HandlerList handlers = new HandlerList();
-        handlers.addHandler(shutdownHandler);
-        handlers.addHandler(contextHandler);
-
-        server.setHandler(handlers);
-
-        server.setConnectors(new Connector[] { connector });
-        try {
-            server.start();
-            server.join();
-        }
-        catch (Exception e) {
-            System.out.println("Server could not be started!");
-            System.out.println(e.getMessage());
-            e.printStackTrace();
-            System.exit(-1);
-        }
-    }
-
-    @Setter
-    public static class KustvaktArgs {
-
-        @Getter
-        private String springConfig;
-        private int port;
-
-        public KustvaktArgs () {
-            this.port = -1;
-            this.springConfig = null;
-        }
-    }
-
-    public String createRandomCode () throws NoSuchAlgorithmException {
-        UUID randomUUID = UUID.randomUUID();
-        byte[] uuidBytes = randomUUID.toString().getBytes();
-        byte[] secureBytes = new byte[3];
-        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
-        secureRandom.nextBytes(secureBytes);
-
-        byte[] bytes = ArrayUtils.addAll(uuidBytes, secureBytes);
-
-        MessageDigest md = MessageDigest.getInstance("MD5");
-        md.update(bytes);
-        byte[] digest = md.digest();
-        String code = Base64.encodeBase64URLSafeString(digest);
-        md.reset();
-        return code;
-    }
-}
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
deleted file mode 100644
index 3873773..0000000
--- a/lite/src/main/java/de/ids_mannheim/korap/web/service/lite/LiteService.java
+++ /dev/null
@@ -1,416 +0,0 @@
-package de.ids_mannheim.korap.web.service.lite;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import javax.annotation.PostConstruct;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-
-import com.sun.jersey.core.util.MultivaluedMapImpl;
-import com.sun.jersey.spi.container.ResourceFilters;
-
-import de.ids_mannheim.korap.config.KustvaktConfiguration;
-import de.ids_mannheim.korap.config.QueryBuilderUtil;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.query.serialize.MetaQueryBuilder;
-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;
-
-/**
- * @author hanl
- * @date 29/01/2014
- * 
- * @author margaretha
- * @update 28/08/2018
- * 
- * <pre>
- * Recent changes:
- * - removed version from service paths
- * - altered service with path /search and method trace to path
- * /query and method get
- * - added API URL versioning
- * </pre>
- */
-@Controller
-@Path("{version}/")
-@ResourceFilters(APIVersionFilter.class)
-@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
-public class LiteService {
-
-    private static Logger jlog = LogManager.getLogger(LiteService.class);
-
-    @Autowired
-    private CoreResponseHandler kustvaktResponseHandler;
-    @Autowired
-    private SearchKrill searchKrill;
-    private ClientsHandler graphDBhandler;
-    @Autowired
-    private RewriteHandler processor;
-    @Autowired
-    private KustvaktConfiguration config;
-
-
-    public LiteService () {
-        // Karang URI
-        UriBuilder builder = UriBuilder.fromUri("http://10.0.10.13").port(9997);
-        this.graphDBhandler = new ClientsHandler(builder.build());
-    }
-
-    @PostConstruct
-    private void init () {
-        processor.defaultRewriteConstraints();
-    }
-    
-    /** Requires Karang (Neo4j search engine)
-     *  
-     * @param query
-     * @return response
-     */
-    @POST
-    @Path("colloc")
-    public Response getCollocationBase (@QueryParam("q") String query) {
-        String result;
-        try {
-            result = graphDBhandler.getResponse("distCollo", "q", query);
-        }
-        catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
-        }
-        return Response.ok(result).build();
-    }
-
-
-    // todo
-    @Deprecated
-    public Response postMatchFavorite () {
-        return Response.ok().build();
-    }
-
-
-    @SuppressWarnings("unchecked")
-    @GET
-    @Path("query")
-    public Response buildQuery (@QueryParam("q") String q,
-            @QueryParam("ql") String ql, @QueryParam("v") String v,
-            @QueryParam("context") String context,
-            @QueryParam("cutoff") Boolean cutoff,
-            @QueryParam("count") Integer pageLength,
-            @QueryParam("offset") Integer pageIndex,
-            @QueryParam("page") Integer startPage,
-            @QueryParam("cq") String cq) {
-        QuerySerializer ss = new QuerySerializer().setQuery(q, ql, v);
-
-        MetaQueryBuilder meta = new MetaQueryBuilder();
-        meta.addEntry("startIndex", pageIndex);
-        if (pageIndex == null && startPage != null)
-            meta.addEntry("startPage", startPage);
-        meta.addEntry("count", pageLength);
-        meta.setSpanContext(context);
-        meta.addEntry("cutOff", cutoff);
-        ss.setMeta(meta.raw());
-        if (cq != null) ss.setCollection(cq);
-
-        String query;
-        try {
-            query = this.processor.processQuery(ss.toJSON(), null);
-        }
-        catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
-        }
-        return Response.ok(query).build();
-    }
-
-
-    @POST
-    @Path("search")
-    public Response queryRaw (@QueryParam("engine") String engine,
-            String jsonld) {
-        try {
-            jsonld = processor.processQuery(jsonld, null);
-        }
-        catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
-        }
-
-		// todo: should be possible to add the meta part to the query serialization
-		jlog.info("Serialized search: "+jsonld);
-		try {
-			String result = searchKrill.search(jsonld);
-			jlog.debug("The result set: "+result);
-			return Response.ok(result).build();
-		}
-		catch (Exception e) {
-			e.printStackTrace();
-		};
-		return Response.ok().build();
-    }
-
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    @GET
-    @Path("search")
-    public Response searchbyNameAll (@QueryParam("q") String q,
-            @QueryParam("ql") String ql, @QueryParam("v") String v,
-            @QueryParam("context") String ctx,
-            @QueryParam("cutoff") Boolean cutoff,
-            @QueryParam("count") Integer pageLength,
-            @QueryParam("offset") Integer pageIndex,
-            @QueryParam("page") Integer pageInteger,
-            @QueryParam("fields") Set<String> fields,
-            // fixme: remove cq value from lightservice
-            @QueryParam("cq") String cq, @QueryParam("engine") String engine) {
-        KustvaktConfiguration.BACKENDS eng = this.config.chooseBackend(engine);
-
-        String result;
-        QuerySerializer serializer = new QuerySerializer().setQuery(q, ql, v);
-        MetaQueryBuilder meta = QueryBuilderUtil.defaultMetaBuilder(pageIndex,
-                pageInteger, pageLength, ctx, cutoff);
-        if (fields != null && !fields.isEmpty())
-            meta.addEntry("fields", fields);
-        serializer.setMeta(meta.raw());
-        if (cq != null) serializer.setCollection(cq);
-
-
-		// There is an error in query processing
-		// - either query, corpus or meta
-		if (serializer.hasErrors()) {
-			// Do not pass further to backend
-			return Response.status(Response.Status.BAD_REQUEST).entity(serializer.toJSON()).build();		
-		}
-
-		
-        String query;
-        try {
-            query = this.processor.processQuery(serializer.toJSON(), null);
-        }
-        catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
-        }
-
-		jlog.info("the serialized query "+ query);
-
-        // This may not work with the the KoralQuery
-        if (eng.equals(KustvaktConfiguration.BACKENDS.NEO4J)) {
-            MultivaluedMap map = new MultivaluedMapImpl();
-            map.add("q", query);
-            map.add("count", String.valueOf(pageLength));
-            map.add("lctxs",
-                    String.valueOf(meta.getSpanContext().getLeftSize()));
-            map.add("rctxs",
-                    String.valueOf(meta.getSpanContext().getRightSize()));
-
-            try {
-                result = this.graphDBhandler.getResponse(map, "distKwic");
-            }
-            catch (KustvaktException e) {
-                throw kustvaktResponseHandler.throwit(e);
-            }
-        }
-        else
-            result = searchKrill.search(query);
-        jlog.debug("The result set: "+ result);
-        return Response.ok(result).build();
-    }
-
-
-    /**
-     * param context will be like this: context: "3-t,2-c"
-     * <p/>
-     * id does not have to be an integer. name is also possible, in
-     * which case a type reference is required
-     * 
-     * @param query
-     * @param ql
-     * @param v
-     * @param ctx
-     * @param cutoff
-     * @param pageLength
-     * @param pageIndex
-     * @param pageInteger
-     * @param id
-     * @param type
-     * @param cq
-     * @param raw
-     * @param engine
-     * @return
-     */
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    //fixme: search in collection /collection/collection-id/search
-    @Deprecated
-    @GET
-    //    @Path("/{type}/{id}/search")
-    public Response searchbyName (@PathParam("id") String id,
-            @PathParam("type") String type, @QueryParam("q") String query,
-            @QueryParam("ql") String ql, @QueryParam("v") String v,
-            @QueryParam("context") String ctx,
-            @QueryParam("cutoff") Boolean cutoff,
-            @QueryParam("count") Integer pageLength,
-            @QueryParam("offset") Integer pageIndex,
-            @QueryParam("page") Integer pageInteger,
-            @QueryParam("cq") String cq, @QueryParam("raw") Boolean raw,
-            @QueryParam("engine") String engine) {
-        // ref is a virtual collection id!
-        KustvaktConfiguration.BACKENDS eng = this.config.chooseBackend(engine);
-        raw = raw == null ? false : raw;
-        MetaQueryBuilder meta = QueryBuilderUtil.defaultMetaBuilder(pageIndex,
-                pageInteger, pageLength, ctx, cutoff);
-        if (!raw) {
-            // should only apply to CQL queries
-            //                meta.addEntry("itemsPerResource", 1);
-            QuerySerializer s = new QuerySerializer().setQuery(query, ql, v)
-                    .setMeta(meta.raw());
-            try {
-                query = this.processor.processQuery(s.toJSON(), null);
-            }
-            catch (KustvaktException e) {
-                throw kustvaktResponseHandler.throwit(e);
-            }
-        }
-        String result;
-        try {
-            if (eng.equals(KustvaktConfiguration.BACKENDS.NEO4J)) {
-                if (raw) throw kustvaktResponseHandler.throwit(
-                        StatusCodes.ILLEGAL_ARGUMENT, "raw not supported!",
-                        null);
-                MultivaluedMap map = new MultivaluedMapImpl();
-                map.add("q", query);
-                map.add("count", String.valueOf(pageLength));
-                map.add("lctxs",
-                        String.valueOf(meta.getSpanContext().getLeftSize()));
-                map.add("rctxs",
-                        String.valueOf(meta.getSpanContext().getRightSize()));
-                result = this.graphDBhandler.getResponse(map, "distKwic");
-            }
-            else
-                result = searchKrill.search(query);
-
-        }
-        catch (Exception e) {
-            jlog.error("Exception for serialized query: " + query, e);
-            throw kustvaktResponseHandler.throwit(500, e.getMessage(), null);
-        }
-
-        jlog.debug("The result set: "+ result);
-        return Response.ok(result).build();
-    }
-
-
-    @GET
-    @Path("statistics")
-    public Response getStatistics (
-            @QueryParam("corpusQuery") String collectionQuery) {
-
-        KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder();
-
-		String stats;
-		if (collectionQuery != null && !collectionQuery.equals("")) {
-			builder.with(collectionQuery);
-			String json;
-			try {
-				json = builder.toJSON();
-			}
-			catch (KustvaktException e) {
-				throw kustvaktResponseHandler.throwit(e);
-			}
-			stats = searchKrill.getStatistics(json);
-		}
-		else {
-			stats = searchKrill.getStatistics(null);
-		};
-
-        if (stats.contains("-1"))
-            throw kustvaktResponseHandler.throwit(StatusCodes.NO_RESULT_FOUND);
-        jlog.debug("Stats: " + stats);
-        return Response.ok(stats).build();
-    }
-
-
-
-    /*
-     * TODO: The problem here is, that the matchinfo path makes no
-     * distinction between docs and texts - unlike DeReKo, the backend
-     * and the frontend. Luckily there is a convenient method
-     * "getMatchID()" for a workaround, but this should be fixed.
-     */
-    @GET
-    @Path("/corpus/{corpusId}/{docId}/{textId}/{matchId}/matchInfo")
-    public Response getMatchInfo (@PathParam("corpusId") String corpusId,
-            @PathParam("docId") String docId,
-            @PathParam("textId") String textId,
-            @PathParam("matchId") String matchId,
-            @QueryParam("foundry") Set<String> foundries,
-            @QueryParam("layer") Set<String> layers,
-            @QueryParam("spans") Boolean spans,
-			// Highlights may also be a list of valid highlight classes
-			@QueryParam("hls") Boolean highlights,
-            @Context HttpServletRequest request) throws KustvaktException {
-
-        String matchid =
-                searchKrill.getMatchId(corpusId, docId, textId, matchId);
-        
-        List<String> f_list = null;
-        List<String> l_list = null;
-        if (layers != null && !layers.isEmpty())
-            l_list = new ArrayList<>(layers);
-
-        if (foundries != null && !foundries.isEmpty()
-                && !foundries.contains("*"))
-            f_list = new ArrayList<>(foundries);
-
-        spans = spans != null ? spans : false;
-        highlights = highlights != null ? highlights : false;
-
-        boolean match_only = foundries == null || foundries.isEmpty();
-        String results;
-        if (match_only)
-            results = searchKrill.getMatch(matchid, null);
-        else
-            results = searchKrill.getMatch(matchid, f_list, l_list, spans,
-                    highlights, true, null);
-
-        return Response.ok(results).build();
-    }
-
-
-	/*
-     * Returns the meta data fields of a certain document
-     */
-    @GET
-    @Path("/corpus/{corpusId}/{docId}/{textId}")
-    public Response getMeta (
-		@PathParam("corpusId") String corpusId,
-		@PathParam("docId") String docId,
-		@PathParam("textId") String textId,
-		// @QueryParam("fields") Set<String> fields,
-		@Context HttpServletRequest request) throws KustvaktException {
-
-		String textSigle = searchKrill.getTextSigle(corpusId, docId, textId);
-		
-		String results = searchKrill.getFields(textSigle);
-
-        return Response.ok(results).build();
-    }
-}
diff --git a/lite/src/main/resources/db/V1__annotation_tables.sql b/lite/src/main/resources/db/V1__annotation_tables.sql
new file mode 100644
index 0000000..b0299d1
--- /dev/null
+++ b/lite/src/main/resources/db/V1__annotation_tables.sql
@@ -0,0 +1,53 @@
+CREATE TABLE IF NOT EXISTS annotation(
+	id INTEGER PRIMARY KEY AUTOINCREMENT,
+	code VARCHAR(20) NOT NULL,
+	type VARCHAR(20) NOT NULL,
+	text VARCHAR(20) NULL,
+	description VARCHAR(100) NOT NULL,
+	de_description VARCHAR(100)
+);
+
+CREATE UNIQUE INDEX annotation_index ON annotation (code, type);
+
+CREATE TABLE IF NOT EXISTS annotation_layer(
+	id INTEGER PRIMARY KEY AUTOINCREMENT,
+	foundry_id INTEGER NOT NULL,
+	layer_id INTEGER NOT NULL,
+	description VARCHAR(255) NOT NULL,
+	FOREIGN KEY (foundry_id)
+		REFERENCES annotation (id)
+		ON DELETE CASCADE,
+	FOREIGN KEY (layer_id)
+		REFERENCES annotation (id)
+		ON DELETE CASCADE
+);
+
+CREATE UNIQUE INDEX annotation_layer_index ON annotation_layer (foundry_id, layer_id);
+
+CREATE TABLE IF NOT EXISTS annotation_key(
+	id INTEGER PRIMARY KEY AUTOINCREMENT,
+	layer_id INTEGER NOT NULL,
+	key_id INTEGER NOT NULL,
+	FOREIGN KEY (layer_id)
+		REFERENCES annotation_layer (id)
+		ON DELETE CASCADE,
+	FOREIGN KEY (key_id)
+		REFERENCES annotation (id)
+		ON DELETE CASCADE
+);
+
+CREATE UNIQUE INDEX annotation_key_index ON annotation_key (layer_id, key_id);
+
+CREATE TABLE IF NOT EXISTS annotation_value(
+	id INTEGER PRIMARY KEY AUTOINCREMENT,
+	key_id INTEGER NOT NULL,
+	value_id INTEGER NOT NULL,
+	FOREIGN KEY (key_id)
+		REFERENCES annotation_key (id)
+		ON DELETE CASCADE,
+	FOREIGN KEY (key_id)
+		REFERENCES annotation (id)
+		ON DELETE CASCADE
+);
+
+CREATE UNIQUE INDEX annotation_value_index ON annotation_value (key_id, value_id);
diff --git a/lite/src/main/resources/hibernate.properties b/lite/src/main/resources/hibernate.properties
new file mode 100644
index 0000000..199dc73
--- /dev/null
+++ b/lite/src/main/resources/hibernate.properties
@@ -0,0 +1,8 @@
+hibernate.dialect=org.hibernate.dialect.MySQLDialect
+hibernate.hbm2ddl.auto=none
+hibernate.show_sql=false
+hibernate.cache.use_query_cache=false
+hibernate.cache.use_second_level_cache=false
+hibernate.cache.provider=org.hibernate.cache.EhCacheProvider
+hibernate.cache.region.factory=org.hibernate.cache.ehcache.EhCacheRegionFactory
+hibernate.jdbc.time_zone=UTC
\ No newline at end of file
diff --git a/lite/src/main/resources/kustvakt-lite.conf b/lite/src/main/resources/kustvakt-lite.conf
index f0dd6b3..db385f0 100644
--- a/lite/src/main/resources/kustvakt-lite.conf
+++ b/lite/src/main/resources/kustvakt-lite.conf
@@ -8,7 +8,6 @@
 
 krill.namedVC=vc
 
-
 # Kustvakt
 
 current.api.version = v1.0
diff --git a/lite/src/main/resources/kustvakt.info b/lite/src/main/resources/kustvakt.info
new file mode 100644
index 0000000..ea847bb
--- /dev/null
+++ b/lite/src/main/resources/kustvakt.info
@@ -0,0 +1,8 @@
+kustvakt.version=${project.version}
+kustvakt.name=${project.name}
+
+# use this file to define the properties and logging file names
+kustvakt.properties=./kustvakt-lite.conf
+kustvakt.logging=./log4j.properties
+kustvakt.cache=true
+kustvakt.cache_store=./store
\ No newline at end of file
diff --git a/lite/src/main/resources/lite-config.xml b/lite/src/main/resources/lite-config.xml
index 671ca33..7c5991c 100644
--- a/lite/src/main/resources/lite-config.xml
+++ b/lite/src/main/resources/lite-config.xml
@@ -1,57 +1,181 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:util="http://www.springframework.org/schema/util"
-       xmlns:context="http://www.springframework.org/schema/context"
-       xmlns="http://www.springframework.org/schema/beans"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
+	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
+           http://www.springframework.org/schema/tx
+           http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/util
            http://www.springframework.org/schema/util/spring-util.xsd">
 
 
-    <context:component-scan base-package="de.ids_mannheim.korap" />
+	<context:component-scan
+		base-package="de.ids_mannheim.korap.web.filter, de.ids_mannheim.korap.web.utils,
+		de.ids_mannheim.korap.authentication.http" />
 	<context:annotation-config />
 
-    <bean id="properties"
-          class="org.springframework.beans.factory.config.PropertiesFactoryBean">
-        <property name="ignoreResourceNotFound" value="true"/>
-        <property name="locations">
-            <array>
-                <value>classpath:kustvakt-lite.conf</value>
-                <value>file:./kustvakt-lite.conf</value>
-            </array>
-        </property>
-    </bean>
-    
-    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
-		<property name="properties">
-			<ref bean="properties"/>
+	<bean id="placeholders"
+		class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
+		<property name="ignoreResourceNotFound" value="true" />
+		<property name="locations">
+			<array>
+				<value>classpath:lite-jdbc.properties</value>
+				<value>file:./lite-jdbc.properties</value>
+				<value>classpath:hibernate.properties</value>
+				<value>classpath:kustvakt-lite.conf</value>
+				<value>file:./kustvakt-lite.conf</value>
+			</array>
 		</property>
 	</bean>
 
-    <bean id="kustvakt_auditing"
-          class="de.ids_mannheim.korap.interfaces.defaults.DefaultAuditing">
-    </bean>
-    
-    <bean id="kustvakt_response"
-          class="de.ids_mannheim.korap.web.CoreResponseHandler">
-          <constructor-arg index="0" name="iface" ref="kustvakt_auditing"/>
-    </bean>
-
-    <bean id="kustvakt_config"
-          class="de.ids_mannheim.korap.config.KustvaktConfiguration">
-        <constructor-arg index="0" name="properties" ref="properties"/>
-    </bean>
-
-    <bean id="kustvakt_rewrite" class="de.ids_mannheim.korap.resource.rewrite.RewriteHandler">
-		<constructor-arg ref="kustvakt_config" />
+	<bean id="properties"
+		class="org.springframework.beans.factory.config.PropertiesFactoryBean">
+		<property name="ignoreResourceNotFound" value="true" />
+		<property name="locations">
+			<array>
+				<value>classpath:kustvakt-lite.conf</value>
+				<value>file:./kustvakt-lite.conf</value>
+			</array>
+		</property>
 	</bean>
-    
-    <bean id="search_krill"
-          class="de.ids_mannheim.korap.web.SearchKrill">
-        <constructor-arg value="${krill.indexDir}"/>
-    </bean>
-    
+
+	<bean id="config" class="de.ids_mannheim.korap.config.KustvaktConfiguration">
+		<constructor-arg index="0" name="properties" ref="properties" />
+	</bean>
+
+	<!-- Database -->
+
+	<bean id="sqliteDataSource"
+		class="org.springframework.jdbc.datasource.SingleConnectionDataSource"
+		lazy-init="true">
+		<property name="driverClassName" value="${jdbc.driverClassName}" />
+		<property name="url" value="${jdbc.url}" />
+		<property name="username" value="${jdbc.username}" />
+		<property name="password" value="${jdbc.password}" />
+		<property name="connectionProperties">
+			<props>
+				<prop key="date_string_format">yyyy-MM-dd HH:mm:ss</prop>
+			</props>
+		</property>
+
+		<!-- relevant for single connection datasource and sqlite -->
+		<property name="suppressClose">
+			<value>true</value>
+		</property>
+		<!--<property name="initialSize" value="2"/> -->
+		<!--<property name="poolPreparedStatements" value="true"/> -->
+	</bean>
+
+	<bean id="flyway" class="org.flywaydb.core.Flyway" init-method="migrate">
+		<property name="baselineOnMigrate" value="true" />
+		<!-- <property name="validateOnMigrate" value="false" /> -->
+		<!-- <property name="cleanOnValidationError" value="true" /> -->
+		<property name="locations" value="${jdbc.schemaPath}" />
+		<property name="dataSource" ref="sqliteDataSource" />
+	</bean>
+
+	<bean id="entityManagerFactory"
+		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
+		<property name="dataSource" ref="sqliteDataSource" />
+
+		<property name="packagesToScan">
+			<array>
+				<value>de.ids_mannheim.korap.entity</value>
+			</array>
+		</property>
+		<property name="jpaVendorAdapter">
+			<bean id="jpaVendorAdapter"
+				class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
+				<property name="databasePlatform" value="${hibernate.dialect}" />
+			</bean>
+		</property>
+		<property name="jpaProperties">
+			<props>
+				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
+				<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
+				<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
+				<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
+				<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}
+				</prop>
+				<prop key="hibernate.cache.provider_class">${hibernate.cache.provider}</prop>
+				<prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory}</prop>
+				<prop key="hibernate.jdbc.time_zone">${hibernate.jdbc.time_zone}</prop>
+			</props>
+		</property>
+	</bean>
+	<tx:annotation-driven proxy-target-class="true"
+		transaction-manager="transactionManager" />
+
+	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
+		<property name="entityManagerFactory" ref="entityManagerFactory" />
+	</bean>
+
+	<bean id="transactionTemplate"
+		class="org.springframework.transaction.support.TransactionTemplate">
+		<constructor-arg ref="transactionManager" />
+	</bean>
+	<bean id="txManager"
+		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
+		<property name="dataSource" ref="sqliteDataSource" />
+	</bean>
+
+	<!-- Initialization -->
+	<bean id="initializator" class="de.ids_mannheim.de.init.LiteInitializatorImpl"
+		init-method="init">
+	</bean>
+	<bean id="annotationParser" class="de.ids_mannheim.korap.annotation.AnnotationParser"
+		scope="singleton" />
+
+	<!-- Krill -->
+	<bean id="search_krill" class="de.ids_mannheim.korap.web.SearchKrill">
+		<constructor-arg value="${krill.indexDir}" />
+	</bean>
+
+	<!-- Filters -->
+	<bean id="APIVersionFilter" class="de.ids_mannheim.korap.web.APIVersionFilter"
+		scope="singleton" />
+
+	<!-- Authentication -->
+	<bean id="authenticationManager"
+		class="de.ids_mannheim.korap.authentication.DummyAuthenticationManager" />
+
+	<!-- Response handler -->
+	<bean id="kustvaktResponseHandler" class="de.ids_mannheim.korap.web.KustvaktResponseHandler">
+		<constructor-arg index="0" name="iface" ref="kustvakt_auditing" />
+	</bean>
+
+	<!-- Controllers -->
+	<bean id="annotationController"
+		class="de.ids_mannheim.korap.web.controller.AnnotationController" />
+	<bean id="searchController" class="de.ids_mannheim.korap.web.controller.SearchController" />
+	<bean id="statisticController"
+		class="de.ids_mannheim.korap.web.controller.StatisticController" />
+
+	<!-- Services -->
+	<bean id="annotationService" class="de.ids_mannheim.korap.service.AnnotationService"></bean>
+	<bean id="scopeService"
+		class="de.ids_mannheim.korap.oauth2.service.DummyOAuth2ScopeServiceImpl" />
+	<bean id="searchService" class="de.ids_mannheim.korap.service.SearchService"></bean>
+
+	<!-- DAO -->
+	<bean id="adminDao" class="de.ids_mannheim.korap.dao.DummyAdminDaoImpl" />
+	<bean id="annotationDao" class="de.ids_mannheim.korap.dao.AnnotationDao" />
+
+	<!-- DTO Converter -->
+	<bean id="annotationConverter" class="de.ids_mannheim.korap.dto.converter.AnnotationConverter" />
+
+	<!-- Rewrite -->
+	<bean id="rewriteHandler" class="de.ids_mannheim.korap.resource.rewrite.RewriteHandler">
+		<constructor-arg ref="config" />
+	</bean>
+
+
+
+	<bean id="kustvakt_auditing"
+		class="de.ids_mannheim.korap.interfaces.defaults.DefaultAuditing">
+	</bean>
+
 </beans>
\ No newline at end of file
diff --git a/lite/src/main/resources/lite-jdbc.properties b/lite/src/main/resources/lite-jdbc.properties
new file mode 100644
index 0000000..99e2e54
--- /dev/null
+++ b/lite/src/main/resources/lite-jdbc.properties
@@ -0,0 +1,9 @@
+#-------------------------------------------------------------------------------
+# Sqlite Settings
+
+jdbc.database=sqlite
+jdbc.driverClassName=org.sqlite.JDBC
+jdbc.url=jdbc:sqlite:liteDB.sqlite
+jdbc.username=pc
+jdbc.password=pc
+jdbc.schemaPath=db
\ No newline at end of file
diff --git a/lite/src/main/resources/log4j2.properties b/lite/src/main/resources/log4j2.properties
index f5e5366..b0115e7 100644
--- a/lite/src/main/resources/log4j2.properties
+++ b/lite/src/main/resources/log4j2.properties
@@ -20,8 +20,8 @@
 logger.console.appenderRefs = stdout
 logger.console.appenderRef.file.ref = STDOUT
 
-#loggers=file
-#logger.file.name=de.ids_mannheim.korap
-#logger.file.level = error
-#logger.file.appenderRefs = file
-#logger.file.appenderRef.file.ref = ERRORLOG
\ No newline at end of file
+loggers=file
+logger.file.name=de.ids_mannheim.korap
+logger.file.level = error
+logger.file.appenderRefs = file
+logger.file.appenderRef.file.ref = ERRORLOG
\ No newline at end of file
diff --git a/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteJerseyTest.java b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteJerseyTest.java
new file mode 100644
index 0000000..a0ea0a3
--- /dev/null
+++ b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteJerseyTest.java
@@ -0,0 +1,54 @@
+package de.ids_mannheim.korap.web.service;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.springframework.web.context.ContextLoaderListener;
+
+import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
+import com.sun.jersey.test.framework.AppDescriptor;
+import com.sun.jersey.test.framework.JerseyTest;
+import com.sun.jersey.test.framework.WebAppDescriptor;
+import com.sun.jersey.test.framework.spi.container.TestContainerException;
+import com.sun.jersey.test.framework.spi.container.TestContainerFactory;
+import com.sun.jersey.test.framework.spi.container.grizzly.web.GrizzlyWebTestContainerFactory;
+
+public class LiteJerseyTest  extends JerseyTest{
+
+    public static final String API_VERSION = "v1.0";
+    private static String[] classPackages =
+            new String[] { "de.ids_mannheim.korap.web.controller",
+                    "de.ids_mannheim.korap.web.filter",
+                    "de.ids_mannheim.korap.web.utils" };
+    @Override
+    protected TestContainerFactory getTestContainerFactory ()
+            throws TestContainerException {
+        return new GrizzlyWebTestContainerFactory();
+    }
+
+    @Override
+    protected AppDescriptor configure () {
+        return new WebAppDescriptor.Builder(classPackages)
+                .servletClass(SpringServlet.class)
+                .contextListenerClass(ContextLoaderListener.class)
+                .contextParam("contextConfigLocation",
+                        "classpath:test-config.xml")
+                .build();
+    }
+
+    @Override
+    protected int getPort (int defaultPort) {
+        int port = ThreadLocalRandom.current().nextInt(5000, 8000 + 1);
+        try {
+            ServerSocket socket = new ServerSocket(port);
+            socket.close();
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+            port = getPort(port);
+        }
+        return port;
+    }
+    
+}
diff --git a/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteSearchControllerTest.java b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteSearchControllerTest.java
new file mode 100644
index 0000000..68088fc
--- /dev/null
+++ b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteSearchControllerTest.java
@@ -0,0 +1,377 @@
+package de.ids_mannheim.korap.web.service;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.net.URI;
+import java.util.Iterator;
+
+import javax.ws.rs.core.MediaType;
+
+import org.eclipse.jetty.http.HttpStatus;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.net.HttpHeaders;
+import com.sun.jersey.api.client.ClientResponse;
+
+import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.query.serialize.QuerySerializer;
+import de.ids_mannheim.korap.utils.JsonUtils;
+
+public class LiteSearchControllerTest extends LiteJerseyTest {
+
+    @Test
+    public void testGetJSONQuery () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("query")
+                .queryParam("q", "[orth=das]").queryParam("ql", "poliqarp")
+                .queryParam("context", "sentence").queryParam("count", "13")
+                .method("GET", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String query = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(query);
+        assertNotNull(node);
+        assertEquals("orth", node.at("/query/wrap/layer").asText());
+        assertEquals("opennlp", node.at("/query/wrap/foundry").asText());
+        assertEquals("sentence", node.at("/meta/context").asText());
+        assertEquals("13", node.at("/meta/count").asText());
+    }
+
+    @Test
+    public void testbuildAndPostQuery () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("query")
+                .queryParam("q", "[orth=das]").queryParam("ql", "poliqarp")
+                .queryParam("cq", "corpusSigle=WPD | corpusSigle=GOE")
+                .method("GET", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        String query = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(query);
+        assertNotNull(node);
+
+        response = resource().path(API_VERSION).path("search")
+                .post(ClientResponse.class, query);
+
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String matches = response.getEntity(String.class);
+        JsonNode match_node = JsonUtils.readTree(matches);
+        assertNotEquals(0, match_node.path("matches").size());
+    }
+
+    @Test
+    public void testQueryGet () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=das]").queryParam("ql", "poliqarp")
+                .queryParam("context", "sentence").queryParam("count", "13")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String query = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(query);
+        assertNotNull(node);
+        assertEquals("orth", node.at("/query/wrap/layer").asText());
+        assertEquals("base/s:s", node.at("/meta/context").asText());
+        assertEquals("13", node.at("/meta/count").asText());
+        assertNotEquals(0, node.at("/matches").size());
+    }
+
+    @Test
+    public void testQueryFailure () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=das").queryParam("ql", "poliqarp")
+                .queryParam("cq", "corpusSigle=WPD | corpusSigle=GOE")
+                .queryParam("count", "13").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String query = response.getEntity(String.class);
+
+        JsonNode node = JsonUtils.readTree(query);
+        assertNotNull(node);
+        assertEquals(302, node.at("/errors/0/0").asInt());
+        assertEquals(302, node.at("/errors/1/0").asInt());
+        assertTrue(node.at("/errors/2").isMissingNode());
+        assertFalse(node.at("/collection").isMissingNode());
+        assertEquals(13, node.at("/meta/count").asInt());
+    }
+
+    @Test
+    public void testFoundryRewrite () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=das]").queryParam("ql", "poliqarp")
+                .queryParam("context", "sentence").queryParam("count", "13")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String query = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(query);
+        assertNotNull(node);
+        assertEquals("orth", node.at("/query/wrap/layer").asText());
+        assertEquals("opennlp", node.at("/query/wrap/foundry").asText());
+    }
+
+    @Test
+    public void testQueryPost () throws KustvaktException {
+        QuerySerializer s = new QuerySerializer();
+        s.setQuery("[orth=das]", "poliqarp");
+
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .post(ClientResponse.class, s.toJSON());
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String query = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(query);
+        assertNotNull(node);
+        assertEquals("orth", node.at("/query/wrap/layer").asText());
+        assertNotEquals(0, node.at("/matches").size());
+    }
+
+    @Test
+    public void testParameterField () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=das]").queryParam("ql", "poliqarp")
+                .queryParam("fields", "author, docSigle")
+                .queryParam("context", "sentence").queryParam("count", "13")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String query = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(query);
+        assertNotNull(node);
+        assertEquals("orth", node.at("/query/wrap/layer").asText());
+        assertNotEquals(0, node.at("/matches").size());
+        assertEquals("[\"author, docSigle\"]",
+                node.at("/meta/fields").toString());
+    }
+
+    @Test
+    public void testMatchInfoGetWithoutSpans () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION)
+                .path("corpus/GOE/AGA/01784/p36-46(5)37-45(2)38-42/matchInfo")
+                .queryParam("foundry", "*").queryParam("spans", "false")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("GOE/AGA/01784", node.at("/textSigle").asText());
+        assertEquals("match-GOE/AGA/01784-p36-46(5)37-45(2)38-42",
+                node.at("/matchID").asText());
+        assertEquals("Belagerung von Mainz", node.at("/title").asText());
+    };
+
+    @Test
+    public void testMatchInfoGetWithoutHighlights () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION)
+                .path("corpus/GOE/AGA/01784/p36-46(5)37-45(2)38-42/matchInfo")
+                .queryParam("foundry", "xy").queryParam("spans", "false")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals(
+                "<span class=\"context-left\"></span><span class=\"match\">der alte freie Weg nach Mainz war gesperrt, ich mußte über die Schiffbrücke bei Rüsselsheim; in Ginsheim ward <mark>gefüttert; der Ort ist sehr zerschossen; dann über die Schiffbrücke</mark> auf die Nonnenaue, wo viele Bäume niedergehauen lagen, sofort auf dem zweiten Teil der Schiffbrücke über den größern Arm des Rheins.</span><span class=\"context-right\"></span>",
+                node.at("/snippet").asText());
+        assertEquals("GOE/AGA/01784", node.at("/textSigle").asText());
+        assertEquals("match-GOE/AGA/01784-p36-46(5)37-45(2)38-42",
+                node.at("/matchID").asText());
+        assertEquals("Belagerung von Mainz", node.at("/title").asText());
+    };
+
+    @Test
+    public void testMatchInfoGetWithHighlights () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION)
+                .path("corpus/GOE/AGA/01784/p36-46(5)37-45(2)38-42/matchInfo")
+                .queryParam("foundry", "xy").queryParam("spans", "false")
+                .queryParam("hls", "true").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("GOE/AGA/01784", node.at("/textSigle").asText());
+        assertEquals(
+                "<span class=\"context-left\"></span><span class=\"match\">"
+                        + "der alte freie Weg nach Mainz war gesperrt, ich mußte über die "
+                        + "Schiffbrücke bei Rüsselsheim; in Ginsheim ward <mark>gefüttert; "
+                        + "<mark class=\"class-5 level-0\">der <mark class=\"class-2 level-1\">"
+                        + "Ort ist sehr zerschossen; dann</mark> über die Schiffbrücke</mark></mark> "
+                        + "auf die Nonnenaue, wo viele Bäume niedergehauen lagen, sofort auf dem "
+                        + "zweiten Teil der Schiffbrücke über den größern Arm des Rheins.</span>"
+                        + "<span class=\"context-right\"></span>",
+                node.at("/snippet").asText());
+        assertEquals("match-GOE/AGA/01784-p36-46(5)37-45(2)38-42",
+                node.at("/matchID").asText());
+        assertEquals("Belagerung von Mainz", node.at("/title").asText());
+    };
+
+    @Test
+    public void testMatchInfoGet2 () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION)
+
+                .path("corpus/GOE/AGA/01784/p36-46/matchInfo")
+                .queryParam("foundry", "*").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("GOE/AGA/01784", node.at("/textSigle").asText());
+        assertEquals("Belagerung von Mainz", node.at("/title").asText());
+    };
+
+    @Test
+    public void testCollectionQueryParameter () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("query")
+                .queryParam("q", "[orth=das]").queryParam("ql", "poliqarp")
+                .queryParam("fields", "author, docSigle")
+                .queryParam("context", "sentence").queryParam("count", "13")
+                .queryParam("cq", "textClass=Politik & corpus=WPD")
+                .method("GET", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String query = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(query);
+        assertNotNull(node);
+        assertEquals("orth", node.at("/query/wrap/layer").asText());
+        assertEquals("Politik",
+                node.at("/collection/operands/0/value").asText());
+        assertEquals("WPD", node.at("/collection/operands/1/value").asText());
+
+        response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=das]").queryParam("ql", "poliqarp")
+                .queryParam("fields", "author, docSigle")
+                .queryParam("context", "sentence").queryParam("count", "13")
+                .queryParam("cq", "textClass=Politik & corpus=WPD")
+                .get(ClientResponse.class);
+        // String version =
+        // LucenePackage.get().getImplementationVersion();;
+        // System.out.println("VERSION "+ version);
+        // System.out.println("RESPONSE "+ response);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        query = response.getEntity(String.class);
+        node = JsonUtils.readTree(query);
+        assertNotNull(node);
+        assertEquals("orth", node.at("/query/wrap/layer").asText());
+        assertEquals("Politik",
+                node.at("/collection/operands/0/value").asText());
+        assertEquals("WPD", node.at("/collection/operands/1/value").asText());
+    }
+
+    @Test
+    public void testMetaFields () throws KustvaktException {
+        ClientResponse response =
+                resource().path(API_VERSION).path("/corpus/GOE/AGA/01784")
+                        .method("GET", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String resp = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(resp);
+        // System.err.println(node.toString());
+
+        Iterator<JsonNode> fieldIter = node.at("/document/fields").elements();
+
+        int checkC = 0;
+        while (fieldIter.hasNext()) {
+            JsonNode field = (JsonNode) fieldIter.next();
+
+            String key = field.at("/key").asText();
+
+            assertEquals("koral:field", field.at("/@type").asText());
+
+            switch (key) {
+                case "textSigle":
+                    assertEquals("type:string", field.at("/type").asText());
+                    assertEquals("GOE/AGA/01784", field.at("/value").asText());
+                    checkC++;
+                    break;
+                case "author":
+                    assertEquals("type:text", field.at("/type").asText());
+                    assertEquals("Goethe, Johann Wolfgang von",
+                            field.at("/value").asText());
+                    checkC++;
+                    break;
+                case "docSigle":
+                    assertEquals("type:string", field.at("/type").asText());
+                    assertEquals("GOE/AGA", field.at("/value").asText());
+                    checkC++;
+                    break;
+                case "docTitle":
+                    assertEquals("type:text", field.at("/type").asText());
+                    assertEquals(
+                            "Goethe: Autobiographische Schriften II, (1817-1825, 1832)",
+                            field.at("/value").asText());
+                    checkC++;
+                    break;
+                case "pubDate":
+                    assertEquals("type:date", field.at("/type").asText());
+                    assertEquals(1982, field.at("/value").asInt());
+                    checkC++;
+                    break;
+            };
+        };
+        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());
+    }
+
+    @Test
+    public void testSearchWithIP () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "Wasser").queryParam("ql", "poliqarp")
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .get(ClientResponse.class);
+
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertTrue(node.at("/collection").isMissingNode());
+    }
+
+    @Test
+    public void testSearchWithAuthorizationHeader () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "Wasser").queryParam("ql", "poliqarp")
+                .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
+                        .createBasicAuthorizationHeaderValue("test", "pwd"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .get(ClientResponse.class);
+
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertTrue(node.at("/collection").isMissingNode());
+    }
+}
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
deleted file mode 100644
index 3578b21..0000000
--- a/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteServiceTest.java
+++ /dev/null
@@ -1,453 +0,0 @@
-package de.ids_mannheim.korap.web.service;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-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;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
-import com.sun.jersey.test.framework.AppDescriptor;
-import com.sun.jersey.test.framework.JerseyTest;
-import com.sun.jersey.test.framework.WebAppDescriptor;
-import com.sun.jersey.test.framework.spi.container.TestContainerException;
-import com.sun.jersey.test.framework.spi.container.TestContainerFactory;
-import com.sun.jersey.test.framework.spi.container.grizzly.web.GrizzlyWebTestContainerFactory;
-
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.query.serialize.QuerySerializer;
-import de.ids_mannheim.korap.utils.JsonUtils;
-
-/**
- * Created by hanl on 29.04.16.
- * 
- * @author margaretha, diewald
- * @date 08/03/2018
- * 
- * Recent changes:
- * - removed test configuration using FastJerseyLightTest
- * - added metadata test
- * - updated field type:date 
- */
-public class LiteServiceTest extends JerseyTest{
-
-    public static final String API_VERSION = "v1.0";
-    public static final String classPackage = "de.ids_mannheim.korap.web.service.lite";
-
-    @Override
-    protected TestContainerFactory getTestContainerFactory ()
-            throws TestContainerException {
-        return new GrizzlyWebTestContainerFactory();
-    }
-
-    @Override
-    protected AppDescriptor configure () {
-        return new WebAppDescriptor.Builder(classPackage)
-                .servletClass(SpringServlet.class)
-                .contextListenerClass(ContextLoaderListener.class)
-                .contextParam("contextConfigLocation",
-                        "classpath:lite-config.xml")
-                .build();
-    }
-
-    @Override
-    protected int getPort (int defaultPort) {
-        int port = ThreadLocalRandom.current().nextInt(5000, 8000 + 1);
-        try {
-            ServerSocket socket = new ServerSocket(port);
-            socket.close();
-        }
-        catch (IOException e) {
-            e.printStackTrace();
-            port = getPort(port);
-        }
-        return port;
-    }
-    
-    @Test
-    public void testStatistics () throws KustvaktException{
-        ClientResponse response = resource().path(API_VERSION)
-                .path("statistics")
-                .queryParam("corpusQuery", "textType=Autobiographie & corpusSigle=GOE")
-                .method("GET", ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String query = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(query);
-        assertEquals(9, node.at("/documents").asInt());
-        assertEquals(527662, node.at("/tokens").asInt());
-        assertEquals(19387, node.at("/sentences").asInt());
-        assertEquals(514, node.at("/paragraphs").asInt());
-    }
-
-	@Test
-    public void testEmptyStatistics () throws KustvaktException{
-        ClientResponse response = resource().path(API_VERSION)
-			.path("statistics")
-			.queryParam("corpusQuery", "")
-			.method("GET", ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String query = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(query);
-        assertEquals(11, node.at("/documents").asInt());
-        assertEquals(665842, node.at("/tokens").asInt());
-        assertEquals(25074, node.at("/sentences").asInt());
-        assertEquals(772, node.at("/paragraphs").asInt());
-
-		response = resource().path(API_VERSION)
-                .path("statistics")
-                .method("GET", ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-		query = response.getEntity(String.class);
-		node = JsonUtils.readTree(query);
-        assertEquals(11, node.at("/documents").asInt());
-        assertEquals(665842, node.at("/tokens").asInt());
-        assertEquals(25074, node.at("/sentences").asInt());
-        assertEquals(772, node.at("/paragraphs").asInt());
-	}
-
-	
-    @Test
-    public void testGetJSONQuery () throws KustvaktException{
-        ClientResponse response = resource().path(API_VERSION)
-                .path("query").queryParam("q", "[orth=das]")
-                .queryParam("ql", "poliqarp").queryParam("context", "sentence")
-                .queryParam("count", "13")
-                .method("GET", ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String query = response.getEntity(String.class);
-//        System.out.println(query);
-        JsonNode node = JsonUtils.readTree(query);
-        assertNotNull(node);
-        assertEquals("orth", node.at("/query/wrap/layer").asText());
-        assertEquals("opennlp", node.at("/query/wrap/foundry").asText());
-        assertEquals("sentence", node.at("/meta/context").asText());
-        assertEquals("13", node.at("/meta/count").asText());
-    }
-
-
-    @Test
-    public void testbuildAndPostQuery () throws KustvaktException{
-        ClientResponse response = resource().path(API_VERSION)
-                .path("query").queryParam("q", "[orth=das]")
-                .queryParam("ql", "poliqarp")
-                .queryParam("cq", "corpusSigle=WPD | corpusSigle=GOE")
-                .method("GET", ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-
-        String query = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(query);
-        assertNotNull(node);
-
-        response = resource().path(API_VERSION).path("search")
-                .post(ClientResponse.class, query);
-
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String matches = response.getEntity(String.class);
-        JsonNode match_node = JsonUtils.readTree(matches);
-        assertNotEquals(0, match_node.path("matches").size());
-    }
-
-
-    @Test
-    public void testQueryGet () throws KustvaktException{
-        ClientResponse response = resource().path(API_VERSION)
-                .path("search").queryParam("q", "[orth=das]")
-                .queryParam("ql", "poliqarp").queryParam("context", "sentence")
-                .queryParam("count", "13").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String query = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(query);
-        assertNotNull(node);
-        assertEquals("orth", node.at("/query/wrap/layer").asText());
-        assertEquals("base/s:s", node.at("/meta/context").asText());
-        assertEquals("13", node.at("/meta/count").asText());
-        assertNotEquals(0, node.at("/matches").size());
-    }
-
-	@Test
-    public void testQueryFailure () throws KustvaktException{
-        ClientResponse response = resource().path(API_VERSION)
-                .path("search").queryParam("q", "[orth=das")
-                .queryParam("ql", "poliqarp")
-                .queryParam("cq", "corpusSigle=WPD | corpusSigle=GOE")
-			.queryParam("count", "13")
-			.get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
-                response.getStatus());
-        String query = response.getEntity(String.class);
-
-		JsonNode node = JsonUtils.readTree(query);
-        assertNotNull(node);
-        assertEquals(302, node.at("/errors/0/0").asInt());
-        assertEquals(302, node.at("/errors/1/0").asInt());
-		assertTrue(node.at("/errors/2").isMissingNode());
-		assertFalse(node.at("/collection").isMissingNode());
-        assertEquals(13, node.at("/meta/count").asInt());
-    }
-
-
-    @Test
-    public void testFoundryRewrite () throws KustvaktException{
-        ClientResponse response = resource().path(API_VERSION)
-                .path("search").queryParam("q", "[orth=das]")
-                .queryParam("ql", "poliqarp").queryParam("context", "sentence")
-                .queryParam("count", "13").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String query = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(query);
-        assertNotNull(node);
-        assertEquals("orth", node.at("/query/wrap/layer").asText());
-        assertEquals("opennlp", node.at("/query/wrap/foundry").asText());
-    }
-
-
-    @Test
-    public void testQueryPost () throws KustvaktException{
-        QuerySerializer s = new QuerySerializer();
-        s.setQuery("[orth=das]", "poliqarp");
-
-        ClientResponse response = resource().path(API_VERSION)
-                .path("search").post(ClientResponse.class, s.toJSON());
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String query = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(query);
-        assertNotNull(node);
-        assertEquals("orth", node.at("/query/wrap/layer").asText());
-        assertNotEquals(0, node.at("/matches").size());
-    }
-
-
-    @Test
-    public void testParameterField () throws KustvaktException{
-        ClientResponse response = resource().path(API_VERSION)
-                .path("search").queryParam("q", "[orth=das]")
-                .queryParam("ql", "poliqarp")
-                .queryParam("fields", "author, docSigle")
-                .queryParam("context", "sentence").queryParam("count", "13")
-                .get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String query = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(query);
-        assertNotNull(node);
-        assertEquals("orth", node.at("/query/wrap/layer").asText());
-        assertNotEquals(0, node.at("/matches").size());
-        assertEquals("[\"author, docSigle\"]", node.at("/meta/fields")
-                .toString());
-    }
-
-	@Test
-	public void testMatchInfoGetWithoutSpans () throws KustvaktException{
-        ClientResponse response = resource().path(API_VERSION)
-			.path("corpus/GOE/AGA/01784/p36-46(5)37-45(2)38-42/matchInfo")
-			.queryParam("foundry", "*")
-			.queryParam("spans", "false")
-			.get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-					 response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertEquals("GOE/AGA/01784", node.at("/textSigle").asText());
-        assertEquals("match-GOE/AGA/01784-p36-46(5)37-45(2)38-42",
-					 node.at("/matchID").asText());
-        assertEquals("Belagerung von Mainz", node.at("/title").asText());
-	};
-
-	@Test
-	public void testMatchInfoGetWithoutHighlights () throws KustvaktException{
-        ClientResponse response = resource().path(API_VERSION)
-			.path("corpus/GOE/AGA/01784/p36-46(5)37-45(2)38-42/matchInfo")
-			.queryParam("foundry", "xy")
-			.queryParam("spans", "false")
-			.get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-					 response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertEquals("<span class=\"context-left\"></span><span class=\"match\">der alte freie Weg nach Mainz war gesperrt, ich mußte über die Schiffbrücke bei Rüsselsheim; in Ginsheim ward <mark>gefüttert; der Ort ist sehr zerschossen; dann über die Schiffbrücke</mark> auf die Nonnenaue, wo viele Bäume niedergehauen lagen, sofort auf dem zweiten Teil der Schiffbrücke über den größern Arm des Rheins.</span><span class=\"context-right\"></span>",
-					 node.at("/snippet").asText());
-        assertEquals("GOE/AGA/01784", node.at("/textSigle").asText());
-        assertEquals("match-GOE/AGA/01784-p36-46(5)37-45(2)38-42",
-					 node.at("/matchID").asText());
-        assertEquals("Belagerung von Mainz", node.at("/title").asText());
-	};
-
-	
-	@Test
-	public void testMatchInfoGetWithHighlights () throws KustvaktException{
-        ClientResponse response = resource().path(API_VERSION)			
-			.path("corpus/GOE/AGA/01784/p36-46(5)37-45(2)38-42/matchInfo")
-			.queryParam("foundry", "xy")
-			.queryParam("spans", "false")
-			.queryParam("hls", "true")
-			.get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-					 response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertEquals("GOE/AGA/01784", node.at("/textSigle").asText());
-        assertEquals("<span class=\"context-left\"></span><span class=\"match\">der alte freie Weg nach Mainz war gesperrt, ich mußte über die Schiffbrücke bei Rüsselsheim; in Ginsheim ward <mark>gefüttert; <mark class=\"class-5 level-0\">der <mark class=\"class-2 level-1\">Ort ist sehr zerschossen; dann</mark> über die Schiffbrücke</mark></mark> auf die Nonnenaue, wo viele Bäume niedergehauen lagen, sofort auf dem zweiten Teil der Schiffbrücke über den größern Arm des Rheins.</span><span class=\"context-right\"></span>",
-					 node.at("/snippet").asText());
-		assertEquals("match-GOE/AGA/01784-p36-46(5)37-45(2)38-42",
-					 node.at("/matchID").asText());
-        assertEquals("Belagerung von Mainz", node.at("/title").asText());
-	};
-
-	
-	@Test
-	public void testMatchInfoGet2 () throws KustvaktException{
-        ClientResponse response = resource().path(API_VERSION)
-			
-			.path("corpus/GOE/AGA/01784/p36-46/matchInfo")
-			.queryParam("foundry", "*")
-			.get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-					 response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertEquals("GOE/AGA/01784", node.at("/textSigle").asText());
-        assertEquals("Belagerung von Mainz", node.at("/title").asText());
-	};
-
-    @Test
-    public void testCollectionQueryParameter () throws KustvaktException{
-        ClientResponse response = resource().path(API_VERSION)
-                .path("query").queryParam("q", "[orth=das]")
-                .queryParam("ql", "poliqarp")
-                .queryParam("fields", "author, docSigle")
-                .queryParam("context", "sentence").queryParam("count", "13")
-                .queryParam("cq", "textClass=Politik & corpus=WPD")
-                .method("GET", ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String query = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(query);
-        assertNotNull(node);
-        assertEquals("orth", node.at("/query/wrap/layer").asText());
-        assertEquals("Politik", node.at("/collection/operands/0/value")
-                .asText());
-        assertEquals("WPD", node.at("/collection/operands/1/value").asText());
-
-        response = resource().path(API_VERSION).path("search")
-                .queryParam("q", "[orth=das]").queryParam("ql", "poliqarp")
-                .queryParam("fields", "author, docSigle")
-                .queryParam("context", "sentence").queryParam("count", "13")
-                .queryParam("cq", "textClass=Politik & corpus=WPD")
-                .get(ClientResponse.class);
-//        String version = LucenePackage.get().getImplementationVersion();;
-//        System.out.println("VERSION "+ version);
-//        System.out.println("RESPONSE "+ response);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        query = response.getEntity(String.class);
-        node = JsonUtils.readTree(query);
-        assertNotNull(node);
-        assertEquals("orth", node.at("/query/wrap/layer").asText());
-        assertEquals("Politik", node.at("/collection/operands/0/value")
-                .asText());
-        assertEquals("WPD", node.at("/collection/operands/1/value").asText());
-    }
-
-	@Test
-	public void testMetaFields () throws KustvaktException {
-        ClientResponse response = resource().path(API_VERSION)
-                .path("/corpus/GOE/AGA/01784")
-                .method("GET", ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String resp = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(resp);
-//		System.err.println(node.toString());
-
-		Iterator<JsonNode> fieldIter = node.at("/document/fields").elements();
-
-		int checkC = 0;
-		while (fieldIter.hasNext()) {
-			JsonNode field = (JsonNode) fieldIter.next();
-
-			String key = field.at("/key").asText();
-
-			assertEquals("koral:field", field.at("/@type").asText());
-
-			switch (key) {
-			case "textSigle":
-				assertEquals("type:string", field.at("/type").asText());
-				assertEquals("GOE/AGA/01784", field.at("/value").asText());
-				checkC++;
-				break;
-			case "author":
-				assertEquals("type:text", field.at("/type").asText());
-				assertEquals("Goethe, Johann Wolfgang von", field.at("/value").asText());
-				checkC++;
-				break;
-			case "docSigle":
-				assertEquals("type:string", field.at("/type").asText());
-				assertEquals("GOE/AGA", field.at("/value").asText());
-				checkC++;
-				break;
-			case "docTitle":
-				assertEquals("type:text", field.at("/type").asText());
-				assertEquals(
-					"Goethe: Autobiographische Schriften II, (1817-1825, 1832)",
-					field.at("/value").asText()
-					);
-				checkC++;
-				break;
-			case "pubDate":
-				assertEquals("type:date", field.at("/type").asText());
-				assertEquals(1982, field.at("/value").asInt());
-				checkC++;
-				break;
-			};		
-		};
-		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());
-    }
-}
diff --git a/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteStatisticControllerTest.java b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteStatisticControllerTest.java
new file mode 100644
index 0000000..0efc39e
--- /dev/null
+++ b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteStatisticControllerTest.java
@@ -0,0 +1,59 @@
+package de.ids_mannheim.korap.web.service;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientResponse;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.utils.JsonUtils;
+
+public class LiteStatisticControllerTest extends LiteJerseyTest{
+
+    @Test
+    public void testStatistics () throws KustvaktException{
+        ClientResponse response = resource().path(API_VERSION)
+                .path("statistics")
+                .queryParam("corpusQuery", "textType=Autobiographie & corpusSigle=GOE")
+                .method("GET", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String query = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(query);
+        assertEquals(9, node.at("/documents").asInt());
+        assertEquals(527662, node.at("/tokens").asInt());
+        assertEquals(19387, node.at("/sentences").asInt());
+        assertEquals(514, node.at("/paragraphs").asInt());
+    }
+
+    @Test
+    public void testEmptyStatistics () throws KustvaktException{
+        ClientResponse response = resource().path(API_VERSION)
+            .path("statistics")
+            .queryParam("corpusQuery", "")
+            .method("GET", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String query = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(query);
+        assertEquals(11, node.at("/documents").asInt());
+        assertEquals(665842, node.at("/tokens").asInt());
+        assertEquals(25074, node.at("/sentences").asInt());
+        assertEquals(772, node.at("/paragraphs").asInt());
+
+        response = resource().path(API_VERSION)
+                .path("statistics")
+                .method("GET", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        query = response.getEntity(String.class);
+        node = JsonUtils.readTree(query);
+        assertEquals(11, node.at("/documents").asInt());
+        assertEquals(665842, node.at("/tokens").asInt());
+        assertEquals(25074, node.at("/sentences").asInt());
+        assertEquals(772, node.at("/paragraphs").asInt());
+    }
+    
+}
diff --git a/lite/src/test/java/de/ids_mannheim/korap/web/service/VCReferenceTest.java b/lite/src/test/java/de/ids_mannheim/korap/web/service/VCReferenceTest.java
deleted file mode 100644
index 2a0bd0c..0000000
--- a/lite/src/test/java/de/ids_mannheim/korap/web/service/VCReferenceTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package de.ids_mannheim.korap.web.service;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.net.ServerSocket;
-import java.util.concurrent.ThreadLocalRandom;
-
-import org.junit.Test;
-import org.springframework.web.context.ContextLoaderListener;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
-import com.sun.jersey.test.framework.AppDescriptor;
-import com.sun.jersey.test.framework.JerseyTest;
-import com.sun.jersey.test.framework.WebAppDescriptor;
-import com.sun.jersey.test.framework.spi.container.TestContainerException;
-import com.sun.jersey.test.framework.spi.container.TestContainerFactory;
-import com.sun.jersey.test.framework.spi.container.grizzly.web.GrizzlyWebTestContainerFactory;
-
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.utils.JsonUtils;
-
-public class VCReferenceTest extends JerseyTest{
-
-    public static final String API_VERSION = "v0.1";
-    public static final String classPackage = "de.ids_mannheim.korap.web.service.lite";
-    
-    @Override
-    protected TestContainerFactory getTestContainerFactory ()
-            throws TestContainerException {
-        return new GrizzlyWebTestContainerFactory();
-    }
-
-    @Override
-    protected AppDescriptor configure () {
-        return new WebAppDescriptor.Builder(classPackage)
-                .servletClass(SpringServlet.class)
-                .contextListenerClass(ContextLoaderListener.class)
-                .contextParam("contextConfigLocation",
-                        "classpath:lite-config.xml")
-                .build();
-    }
-
-    @Override
-    protected int getPort (int defaultPort) {
-        int port = ThreadLocalRandom.current().nextInt(5000, 8000 + 1);
-        try {
-            ServerSocket socket = new ServerSocket(port);
-            socket.close();
-        }
-        catch (IOException e) {
-            e.printStackTrace();
-            port = getPort(port);
-        }
-        return port;
-    }
-    
-    @Test
-    public void testSearchWithVCRef () throws KustvaktException {
-        ClientResponse response = resource().path(API_VERSION).path("search")
-                .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
-                .queryParam("cq", "referTo named-vc1")
-                .get(ClientResponse.class);
-
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertTrue(node.at("/matches").size() > 0);
-
-    }
-    
-    @Test
-    public void testStatisticsWithVCReference () throws KustvaktException {
-        String corpusQuery = "referTo named-vc1";
-        ClientResponse response = resource().path(API_VERSION).path("statistics")
-                .queryParam("corpusQuery", corpusQuery)
-                .get(ClientResponse.class);
-
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertEquals(2, node.at("/documents").asInt());
-    }
-}
diff --git a/lite/src/test/resources/test-config.xml b/lite/src/test/resources/test-config.xml
new file mode 100644
index 0000000..abfb505
--- /dev/null
+++ b/lite/src/test/resources/test-config.xml
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
+	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+           http://www.springframework.org/schema/beans/spring-beans.xsd
+           http://www.springframework.org/schema/tx
+           http://www.springframework.org/schema/tx/spring-tx.xsd
+           http://www.springframework.org/schema/context
+           http://www.springframework.org/schema/context/spring-context.xsd
+           http://www.springframework.org/schema/util
+           http://www.springframework.org/schema/util/spring-util.xsd">
+
+
+	<context:component-scan
+		base-package="de.ids_mannheim.korap.web.filter, de.ids_mannheim.korap.web.utils,
+		de.ids_mannheim.korap.authentication.http" />
+	<context:annotation-config />
+
+	<bean id="placeholders"
+		class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
+		<property name="ignoreResourceNotFound" value="true" />
+		<property name="locations">
+			<array>
+				<value>classpath:test-jdbc.properties</value>
+				<value>file:./test-jdbc.properties</value>
+				<value>classpath:hibernate.properties</value>
+				<value>classpath:kustvakt-lite.conf</value>
+				<value>file:./kustvakt-lite.conf</value>
+			</array>
+		</property>
+	</bean>
+
+	<bean id="properties"
+		class="org.springframework.beans.factory.config.PropertiesFactoryBean">
+		<property name="ignoreResourceNotFound" value="true" />
+		<property name="locations">
+			<array>
+				<value>classpath:kustvakt-lite.conf</value>
+				<value>file:./kustvakt-lite.conf</value>
+			</array>
+		</property>
+	</bean>
+
+	<bean id="config" class="de.ids_mannheim.korap.config.KustvaktConfiguration">
+		<constructor-arg index="0" name="properties" ref="properties" />
+	</bean>
+
+	<!-- Database -->
+
+	<bean id="sqliteDataSource"
+		class="org.springframework.jdbc.datasource.SingleConnectionDataSource"
+		lazy-init="true">
+		<property name="driverClassName" value="${jdbc.driverClassName}" />
+		<property name="url" value="${jdbc.url}" />
+		<property name="username" value="${jdbc.username}" />
+		<property name="password" value="${jdbc.password}" />
+		<property name="connectionProperties">
+			<props>
+				<prop key="date_string_format">yyyy-MM-dd HH:mm:ss</prop>
+			</props>
+		</property>
+
+		<!-- relevant for single connection datasource and sqlite -->
+		<property name="suppressClose">
+			<value>true</value>
+		</property>
+		<!--<property name="initialSize" value="2"/> -->
+		<!--<property name="poolPreparedStatements" value="true"/> -->
+	</bean>
+
+	<bean id="flyway" class="org.flywaydb.core.Flyway" init-method="migrate">
+		<property name="baselineOnMigrate" value="true" />
+		<!-- <property name="validateOnMigrate" value="false" /> -->
+		<!-- <property name="cleanOnValidationError" value="true" /> -->
+		<property name="locations" value="${jdbc.schemaPath}" />
+		<property name="dataSource" ref="sqliteDataSource" />
+	</bean>
+
+	<bean id="entityManagerFactory"
+		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
+		<property name="dataSource" ref="sqliteDataSource" />
+
+		<property name="packagesToScan">
+			<array>
+				<value>de.ids_mannheim.korap.entity</value>
+			</array>
+		</property>
+		<property name="jpaVendorAdapter">
+			<bean id="jpaVendorAdapter"
+				class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
+				<property name="databasePlatform" value="${hibernate.dialect}" />
+			</bean>
+		</property>
+		<property name="jpaProperties">
+			<props>
+				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
+				<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
+				<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
+				<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
+				<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}
+				</prop>
+				<prop key="hibernate.cache.provider_class">${hibernate.cache.provider}</prop>
+				<prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory}</prop>
+				<prop key="hibernate.jdbc.time_zone">${hibernate.jdbc.time_zone}</prop>
+			</props>
+		</property>
+	</bean>
+	<tx:annotation-driven proxy-target-class="true"
+		transaction-manager="transactionManager" />
+
+	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
+		<property name="entityManagerFactory" ref="entityManagerFactory" />
+	</bean>
+
+	<bean id="transactionTemplate"
+		class="org.springframework.transaction.support.TransactionTemplate">
+		<constructor-arg ref="transactionManager" />
+	</bean>
+	<bean id="txManager"
+		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
+		<property name="dataSource" ref="sqliteDataSource" />
+	</bean>
+
+	<!-- Initialization -->
+	<bean id="initializator" class="de.ids_mannheim.de.init.LiteInitializatorImpl"
+		init-method="init">
+	</bean>
+	<bean id="annotationParser" class="de.ids_mannheim.korap.annotation.AnnotationParser"
+		scope="singleton" />
+
+	<!-- Krill -->
+	<bean id="search_krill" class="de.ids_mannheim.korap.web.SearchKrill">
+		<constructor-arg value="${krill.indexDir}" />
+	</bean>
+
+	<!-- Filters -->
+	<bean id="APIVersionFilter" class="de.ids_mannheim.korap.web.APIVersionFilter"
+		scope="singleton" />
+
+	<!-- Authentication -->
+	<bean id="authenticationManager"
+		class="de.ids_mannheim.korap.authentication.DummyAuthenticationManager" />
+
+	<!-- Response handler -->
+	<bean id="kustvaktResponseHandler" class="de.ids_mannheim.korap.web.KustvaktResponseHandler">
+		<constructor-arg index="0" name="iface" ref="kustvakt_auditing" />
+	</bean>
+
+	<!-- Controllers -->
+	<bean id="annotationController"
+		class="de.ids_mannheim.korap.web.controller.AnnotationController" />
+	<bean id="searchController" class="de.ids_mannheim.korap.web.controller.SearchController" />
+	<bean id="statisticController"
+		class="de.ids_mannheim.korap.web.controller.StatisticController" />
+
+	<!-- Services -->
+	<bean id="annotationService" class="de.ids_mannheim.korap.service.AnnotationService"></bean>
+	<bean id="scopeService"
+		class="de.ids_mannheim.korap.oauth2.service.DummyOAuth2ScopeServiceImpl" />
+	<bean id="searchService" class="de.ids_mannheim.korap.service.SearchService"></bean>
+
+	<!-- DAO -->
+	<bean id="adminDao" class="de.ids_mannheim.korap.dao.DummyAdminDaoImpl" />
+	<bean id="annotationDao" class="de.ids_mannheim.korap.dao.AnnotationDao" />
+
+	<!-- DTO Converter -->
+	<bean id="annotationConverter" class="de.ids_mannheim.korap.dto.converter.AnnotationConverter" />
+
+	<!-- Rewrite -->
+	<bean id="rewriteHandler" class="de.ids_mannheim.korap.resource.rewrite.RewriteHandler">
+		<constructor-arg ref="config" />
+	</bean>
+
+
+
+	<bean id="kustvakt_auditing"
+		class="de.ids_mannheim.korap.interfaces.defaults.DefaultAuditing">
+	</bean>
+
+</beans>
\ No newline at end of file
diff --git a/lite/src/test/resources/test-jdbc.properties b/lite/src/test/resources/test-jdbc.properties
new file mode 100644
index 0000000..99e2e54
--- /dev/null
+++ b/lite/src/test/resources/test-jdbc.properties
@@ -0,0 +1,9 @@
+#-------------------------------------------------------------------------------
+# Sqlite Settings
+
+jdbc.database=sqlite
+jdbc.driverClassName=org.sqlite.JDBC
+jdbc.url=jdbc:sqlite:liteDB.sqlite
+jdbc.username=pc
+jdbc.password=pc
+jdbc.schemaPath=db
\ No newline at end of file