diff --git a/.gitignore b/.gitignore
index 098193d38aa968488888f4e4e112622e9d73bb9d..dfaa205dd6b38ab1f8b9cc25d5cef7386cb0c7b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@ bin/
 .project
 t14-test-images
 log/
+config.properties
 
 # User-specific stuff
 .idea/**/workspace.xml
@@ -79,3 +80,5 @@ fabric.properties
 
 # Android studio 3.1+ serialized cache file
 .idea/caches/build_file_checksums.ser
+
+config.properties
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b053587b98b9abee0579207b87f55d4972991cad..5eed0fbd37cde9069dd3158d9cbc173c43d713f3 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -4,6 +4,11 @@ stages:
   - build
   - test
 
+# Cache downloaded dependencies and plugins between builds.
+cache:
+  paths:
+    - /root/.m2/repository/
+
 build:
   stage: build
   only:
diff --git a/config.test.properties b/config.test.properties
new file mode 100644
index 0000000000000000000000000000000000000000..e4db66512ba4b4d918189a4d7ebedbc6da3f7b99
--- /dev/null
+++ b/config.test.properties
@@ -0,0 +1,4 @@
+# Test Database Connection Properties
+DB_DRIVER=org.h2.Driver
+DB_URL=jdbc:h2:mem:test_db;DB_CLOSE_DELAY=-1
+DB_DIALECT=org.hibernate.dialect.H2Dialect
diff --git a/javadoc/NTNU/IDATT1002/database/EntityManagerConfig.html b/javadoc/NTNU/IDATT1002/database/EntityManagerConfig.html
index f0727075cd319fa8dde338d76625f16716785ac7..47f7d6594fbb6bd003b91394d18705d552be6820 100644
--- a/javadoc/NTNU/IDATT1002/database/EntityManagerConfig.html
+++ b/javadoc/NTNU/IDATT1002/database/EntityManagerConfig.html
@@ -124,7 +124,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
 <li>java.lang.Object</li>
 <li>
 <ul class="inheritance">
-<li>NTNU.IDATT1002.database.EntityManagerConfig</li>
+<li>NTNU.IDATT1002.Config</li>
 </ul>
 </li>
 </ul>
diff --git a/pom.xml b/pom.xml
index f409895eb63887dec5a35219fb099f42a6aa5566..aa7c61bb3ff675b078230469ada1fb9a8a53b529 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,11 +38,13 @@
             <artifactId>hibernate-jpa-2.1-api</artifactId>
             <version>1.0.2.Final</version>
         </dependency>
+
         <dependency> 
             <groupId>org.hibernate.validator</groupId>
             <artifactId>hibernate-validator</artifactId>
             <version>6.1.0.Final</version>
         </dependency>
+
         <dependency>
             <groupId>javax.xml.bind</groupId>
             <artifactId>jaxb-api</artifactId>
@@ -69,6 +71,12 @@
             <version>13</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.openjfx</groupId>
+            <artifactId>javafx-base</artifactId>
+            <version>15-ea+2</version>
+        </dependency>
+
         <dependency>
             <groupId>org.openjfx</groupId>
             <artifactId>javafx-web</artifactId>
@@ -115,6 +123,7 @@
             <artifactId>junit</artifactId>
             <version>4.13</version>
         </dependency>
+
         <dependency>
             <groupId>com.h2database</groupId>
             <artifactId>h2</artifactId>
@@ -135,7 +144,7 @@
             <version>1.56</version>
         </dependency>
 
-        <!-- Google Maps API -->
+        <!-- GMapsFX -->
         <dependency>
             <groupId>com.lynden</groupId>
             <artifactId>GMapsFX</artifactId>
@@ -149,6 +158,20 @@
             </exclusions>
         </dependency>
 
+        <!-- Google Maps API Client -->
+        <dependency>
+            <groupId>com.google.maps</groupId>
+            <artifactId>google-maps-services</artifactId>
+            <version>0.11.0</version>
+        </dependency>
+
+        <!-- JavaFX Controls -->
+        <dependency>
+            <groupId>org.controlsfx</groupId>
+            <artifactId>controlsfx</artifactId>
+            <version>11.0.0</version>
+        </dependency>
+
     </dependencies>
     <build>
         <plugins>
@@ -169,6 +192,10 @@
                 <configuration>
                     <mainClass>NTNU.IDATT1002.App</mainClass>
                     <executable>${java.home}\bin\java</executable>
+                    <options>
+                        <options>--add-exports</options>
+                        <options>javafx.base/com.sun.javafx.event=org.controlsfx.controls</options>
+                    </options>
                 </configuration>
             </plugin>
 
@@ -176,6 +203,11 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
                 <version>2.22.0</version>
+                <configuration>
+                    <systemPropertyVariables>
+                        <config_properties>config.test.properties</config_properties>
+                    </systemPropertyVariables>
+                </configuration>
             </plugin>
 
             <plugin>
diff --git a/src/main/java/NTNU/IDATT1002/App.java b/src/main/java/NTNU/IDATT1002/App.java
index 5693e0798588f46a158ff04a866a4ce22fb8d1e3..08a1c6063cfdcc25b9540808a64d57dc044b8513 100644
--- a/src/main/java/NTNU/IDATT1002/App.java
+++ b/src/main/java/NTNU/IDATT1002/App.java
@@ -26,6 +26,14 @@ public class App extends Application {
         stage.show();
     }
 
+    /**
+     * Shut down GeoApiContext on application stop to gracefully close the connection.
+     */
+    @Override
+    public void stop(){
+       ex.getGeoApiContext().shutdown();
+    }
+
     public static void setRoot(String fxml) throws IOException {
         scene.setRoot(loadFXML(fxml));
     }
diff --git a/src/main/java/NTNU/IDATT1002/ApplicationState.java b/src/main/java/NTNU/IDATT1002/ApplicationState.java
index cc727dcaa48d7e397c8ece1723e2e3f5fff2be11..640517cb58ddd22edd63dc4ff65cbe8d553d4e67 100644
--- a/src/main/java/NTNU/IDATT1002/ApplicationState.java
+++ b/src/main/java/NTNU/IDATT1002/ApplicationState.java
@@ -1,7 +1,6 @@
 package NTNU.IDATT1002;
 
 
-import NTNU.IDATT1002.database.EntityManagerConfig;
 import NTNU.IDATT1002.models.User;
 import NTNU.IDATT1002.repository.UserRepository;
 
@@ -28,7 +27,7 @@ public final class ApplicationState {
      * Initiate properties and save an anonymous user once.
      */
     static {
-        EntityManager entityManager = EntityManagerConfig.getEntityManager();
+        EntityManager entityManager = Config.getEntityManager();
 
         userRepository = new UserRepository(entityManager);
     }
diff --git a/src/main/java/NTNU/IDATT1002/Config.java b/src/main/java/NTNU/IDATT1002/Config.java
new file mode 100644
index 0000000000000000000000000000000000000000..f454f18da2a0fc86291b0c8f317ce38c133f6f20
--- /dev/null
+++ b/src/main/java/NTNU/IDATT1002/Config.java
@@ -0,0 +1,94 @@
+package NTNU.IDATT1002;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+
+/**
+ * Application Configuration Singleton for parsing hibernate persistence properties and Google Maps API key.
+ * Provides a single global access point to the applications entity manager.
+ */
+public class Config {
+
+    private static EntityManager entityManager;
+    private static Map<String, Object> configOverrides = new HashMap<>();
+    private static Properties properties = loadProperties();
+    private static Logger logger = LoggerFactory.getLogger(Config.class);
+
+    private Config() {
+    }
+
+    /**
+     * Load properties from configured properties file. Defaults to config.properties.
+     *
+     * @return the properties
+     */
+    private static Properties loadProperties() {
+        String configFile = System.getProperty("config_properties", "config.properties");
+
+        Properties environmentProperties = new Properties();
+        try (InputStream input = new FileInputStream(configFile)) {
+            environmentProperties.load(input);
+        } catch (IOException ex) {
+            logger.error("[x] Failed to load config properties", ex);
+        }
+
+        return environmentProperties;
+    }
+
+    public static String getGoogleApiKey() {
+        return properties.getProperty("GOOGLE_API_KEY");
+    }
+
+    /**
+     * Retrieve the entity manager instance.
+     * An entity manager is not created until it is requested.
+     *
+     * @return an entity manager instance
+     */
+    public static EntityManager getEntityManager() {
+        if (entityManager == null)
+            configureEntityManager();
+
+        return entityManager;
+    }
+
+    /**
+     * Parse properties and create the entity manager
+     */
+    private static void configureEntityManager() {
+        parseConfigProperties();
+        createEntityManager();
+    }
+
+    /**
+     * Parse properties and override config.
+     */
+    private static void parseConfigProperties() {
+        configOverrides.put("javax.persistence.jdbc.driver", properties.getProperty("DB_DRIVER"));
+        configOverrides.put("javax.persistence.jdbc.url", properties.get("DB_URL"));
+        configOverrides.put("javax.persistence.jdbc.user", properties.get("DB_USER"));
+        configOverrides.put("javax.persistence.jdbc.password", properties.get("DB_PASSWORD"));
+        configOverrides.put("hibernate.dialect", properties.get("DB_DIALECT"));
+    }
+
+
+    /**
+     * Create an entity manager with configurations overrides.
+     */
+    private static void createEntityManager() {
+        EntityManagerFactory emf = Persistence.createEntityManagerFactory("ImageApplication", configOverrides);
+        entityManager = emf.createEntityManager();
+    }
+
+}
diff --git a/src/main/java/NTNU/IDATT1002/controllers/DataExchange.java b/src/main/java/NTNU/IDATT1002/controllers/DataExchange.java
index a05ec283cb46a8b055e7a26adf8cf3d0d2f11de3..8dc0bb97fa6f8a28e638b8b25f0ea4f3a2b87371 100644
--- a/src/main/java/NTNU/IDATT1002/controllers/DataExchange.java
+++ b/src/main/java/NTNU/IDATT1002/controllers/DataExchange.java
@@ -1,6 +1,7 @@
 package NTNU.IDATT1002.controllers;
 
-import NTNU.IDATT1002.database.EntityManagerConfig;
+import NTNU.IDATT1002.Config;
+import com.google.maps.GeoApiContext;
 import javafx.application.HostServices;
 
 import javax.persistence.EntityManager;
@@ -14,8 +15,9 @@ import java.util.List;
  */
 public class DataExchange {
 
-    private EntityManager entityManager;
+    private String apiKey;
     public HostServices hostServices;
+    private GeoApiContext geoApiContext;
     private String searchField;
     private List<File> uploadedFiles;
     private Long chosenAlbumId;
@@ -23,16 +25,28 @@ public class DataExchange {
 
     public DataExchange(){
         searchField = "";
+        apiKey = Config.getGoogleApiKey();
+        geoApiContext = new GeoApiContext.Builder()
+                .apiKey(getApiKey())
+                .build();
     }
 
     public EntityManager getEntityManager() {
-        return EntityManagerConfig.getEntityManager();
+        return Config.getEntityManager();
+    }
+
+    public String getApiKey() {
+        return apiKey;
     }
 
     public HostServices getHostServices() {
         return hostServices;
     }
 
+    public GeoApiContext getGeoApiContext() {
+        return geoApiContext;
+    }
+
     public List<File> getUploadedFiles() {
         return uploadedFiles;
     }
@@ -49,10 +63,6 @@ public class DataExchange {
         return chosenImg;
     }
 
-    public void setEntityManager(EntityManager entityManager) {
-        this.entityManager = entityManager;
-    }
-
     public void setHostServices(HostServices hostServices) {
         this.hostServices = hostServices;
     }
diff --git a/src/main/java/NTNU/IDATT1002/controllers/ImageMapFactory.java b/src/main/java/NTNU/IDATT1002/controllers/ImageMapFactory.java
index 701fa4217d3182da7c4a9254963869caa969bbbd..a1c4c11af6426ae95dc08ab4a73954534d953c58 100644
--- a/src/main/java/NTNU/IDATT1002/controllers/ImageMapFactory.java
+++ b/src/main/java/NTNU/IDATT1002/controllers/ImageMapFactory.java
@@ -1,5 +1,6 @@
 package NTNU.IDATT1002.controllers;
 
+import NTNU.IDATT1002.models.GeoLocation;
 import NTNU.IDATT1002.models.Image;
 import com.lynden.gmapsfx.GoogleMapView;
 import com.lynden.gmapsfx.javascript.object.*;
@@ -23,42 +24,14 @@ public class ImageMapFactory {
     private ImageMapFactory() {}
 
     /**
-     * Create a map from given {@link GoogleMapView} with default options and markers for images in given list.
+     * Create a map from given {@link GoogleMapView} with default options.
      *
      * @param googleMapView the map view to add the map to
-     * @param images the list of images to place on the map
      * @return the {@link GoogleMap} created to enable further customization
      */
-    public static GoogleMap createMap(GoogleMapView googleMapView, List<Image> images) {
-        List<LatLong> locations = getLatLongs(images);
-
+    public static GoogleMap createMap(GoogleMapView googleMapView) {
         MapOptions mapOptions = getMapOptions();
-        GoogleMap googleMap = googleMapView.createMap(mapOptions);
-        logger.info("[x] Google map created with {} locations", locations.size());
-
-        List<Marker> markers = getMarkers(locations);
-        googleMap.addMarkers(markers);
-        logger.info("[x] {} markers added", markers.size());
-
-        return googleMap;
-    }
-
-
-    /**
-     * Get latitude and longitude ({@link LatLong}) values for given images.
-     *
-     * @param images the list of images
-     * @return a list of {@link LatLong}
-     */
-    private static List<LatLong> getLatLongs(List<Image> images) {
-        return images.stream()
-                .map(Image::getGeoLocation)
-                .map(geoLocation -> {
-                    double latitude = Double.parseDouble(geoLocation.getLatitude());
-                    double longitude = Double.parseDouble(geoLocation.getLongitude());
-                    return new LatLong(latitude, longitude);
-                })
-                .collect(Collectors.toList());
+        return googleMapView.createMap(mapOptions);
     }
 
     /**
@@ -81,6 +54,37 @@ public class ImageMapFactory {
                 .zoom(3);
     }
 
+    /**
+     * Create markers from given images.
+     *
+     * @param images the list of images
+     * @return a list of markers created from the images
+     */
+    public static List<Marker> createMarkers(List<Image> images) {
+        List<LatLong> locations = getLatLongs(images);
+        List<Marker> markers = getMarkers(locations);
+        logger.info("[x] {} markers created", markers.size());
+        return markers;
+    }
+
+    /**
+     * Get latitude and longitude ({@link LatLong}) values for given images.
+     *
+     * @param images the list of images
+     * @return a list of {@link LatLong}
+     */
+    private static List<LatLong> getLatLongs(List<Image> images) {
+        return images.stream()
+                .map(Image::getGeoLocation)
+                .filter(GeoLocation::hasLatLong)
+                .map(geoLocation -> {
+                    double latitude = Double.parseDouble(geoLocation.getLatitude());
+                    double longitude = Double.parseDouble(geoLocation.getLongitude());
+                    return new LatLong(latitude, longitude);
+                })
+                .collect(Collectors.toList());
+    }
+
     /**
      * Create {@link Marker}s for each location in given list of locations.
      *
@@ -97,4 +101,5 @@ public class ImageMapFactory {
                 })
                 .collect(Collectors.toList());
     }
+
 }
diff --git a/src/main/java/NTNU/IDATT1002/controllers/Map.java b/src/main/java/NTNU/IDATT1002/controllers/Map.java
index 65274811f52926cf5068dce502fc0195d7bd5184..a0cc06fa5686c09e1c2657045131316a03df4970 100644
--- a/src/main/java/NTNU/IDATT1002/controllers/Map.java
+++ b/src/main/java/NTNU/IDATT1002/controllers/Map.java
@@ -5,18 +5,29 @@ import NTNU.IDATT1002.models.Album;
 import NTNU.IDATT1002.models.Image;
 import NTNU.IDATT1002.service.AlbumService;
 import NTNU.IDATT1002.service.ImageService;
+import com.google.maps.*;
+import com.google.maps.model.AutocompletePrediction;
+import com.google.maps.model.GeocodingResult;
+import com.google.maps.model.LatLng;
 import com.lynden.gmapsfx.GoogleMapView;
 import com.lynden.gmapsfx.MapComponentInitializedListener;
 import com.lynden.gmapsfx.javascript.object.GoogleMap;
-import java.util.Optional;
+import com.lynden.gmapsfx.javascript.object.LatLong;
+import com.lynden.gmapsfx.javascript.object.Marker;
+import javafx.application.Platform;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
 import javafx.concurrent.Task;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
 import javafx.fxml.Initializable;
+import javafx.scene.control.Alert;
 import javafx.scene.control.Button;
 import javafx.scene.control.TextField;
 import javafx.scene.image.ImageView;
+import javafx.scene.input.KeyEvent;
 import javafx.scene.input.MouseEvent;
+import org.controlsfx.control.textfield.TextFields;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -25,9 +36,13 @@ import java.io.IOException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 import java.util.ResourceBundle;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
 
 /**
  * Controls the buttons and changeable elements on map.fxml,
@@ -48,11 +63,22 @@ public class Map implements Initializable, MapComponentInitializedListener {
 
     @FXML
     private GoogleMapView mapView;
-    private GoogleMap map;
+
+    @FXML
+    private TextField addressTextField;
+
+    private List<String> autoCompletions = new ArrayList<>();
+
+    private GoogleMap googleMap;
+
+    private GeoApiContext geoApiContext;
+
+    private StringProperty address = new SimpleStringProperty();
 
     private ImageService imageService;
     private AlbumService albumService;
     private ExecutorService executorService = Executors.newCachedThreadPool();
+
     private static Logger logger = LoggerFactory.getLogger(Map.class);
 
 
@@ -63,51 +89,54 @@ public class Map implements Initializable, MapComponentInitializedListener {
     }
 
     /**
-     * Register the api key for Google Maps API and listen for map initialization
-     * in order to update the view once it has been initialized.
+     * Initialize {@link GoogleMapView} and {@link GeoApiContext} with required API key.
+     * Also add listener for map initialization and bind the address text field to a {@link SimpleStringProperty}.
      *
      * @param url
      * @param rb
      */
     @Override
     public void initialize(URL url, ResourceBundle rb) {
-        mapView.setKey("AIzaSyB_ox5XC8zYBS__aezKumB-KSgKGUjcRx4");
+        mapView.setKey(App.ex.getApiKey());
         mapView.addMapInializedListener(this);
-    }
+        address.bind(addressTextField.textProperty());
 
+        geoApiContext = App.ex.getGeoApiContext();
+    }
 
     /**
-     * Check is there is a current album in dataexchange first and uses images from album to display on map.
-     * If none is found it proceeds to get all images available and display on map
+     * Create map an fetch images from the appropriate task and add individual markers for images.
      */
     @Override
     public void mapInitialized() {
-        List<Image> albumImages = new ArrayList<>();
-        Long currentAlbumId;
+        googleMap = ImageMapFactory.createMap(mapView);
+        
+        Task<List<Image>> fetchImagesTask = getImageListTask();
+        executorService.submit(fetchImagesTask);
 
-        if(App.ex.getChosenAlbumId() == null) {
-            executorService.submit(fetchImages);
+        fetchImagesTask.setOnSucceeded(workerStateEvent -> {
+            List<Image> images = fetchImagesTask.getValue();
+            List<Marker> markers = ImageMapFactory.createMarkers(images);
+            googleMap.addMarkers(markers);
+        });
+    }
 
-            fetchImages.setOnSucceeded(workerStateEvent -> {
-                List<Image> allImages = fetchImages.getValue();
-                ImageMapFactory.createMap(mapView, allImages);
-            });
-        }
-        else {
-            currentAlbumId = App.ex.getChosenAlbumId();
-            Optional<Album> optionalAlbum = albumService.getAlbumById(currentAlbumId);
-            if (optionalAlbum.isPresent()) {
-                Album album = optionalAlbum.get();
-                albumImages = album.getImages();
-            }
-            ImageMapFactory.createMap(mapView, albumImages);
-        }
+    /**
+     * Decide which images to fetch. Fetch album images if user is trying to view album, else all images.
+     *
+     * @return a task which fetches images
+     */
+    private Task<List<Image>> getImageListTask() {
+        if (App.ex.getChosenAlbumId() == null)
+            return fetchAllImages;
+
+        return fetchAlbumImages;
     }
 
     /**
      * Background task for fetching all images.
      */
-    private Task<List<Image>> fetchImages = new Task<>() {
+    private Task<List<Image>> fetchAllImages = new Task<>() {
         @Override
         protected List<Image> call() {
             try {
@@ -120,7 +149,103 @@ public class Map implements Initializable, MapComponentInitializedListener {
     };
 
     /**
-     * Change scene to Main page
+     * Background task for fetching all images in the current chosen album
+     * in {@link DataExchange}.
+     */
+    private Task<List<Image>> fetchAlbumImages =  new Task<>() {
+        @Override
+        protected List<Image> call() {
+            try {
+                Optional<Album> optionalAlbum = albumService.getAlbumById(App.ex.getChosenAlbumId());
+
+                if (optionalAlbum.isPresent())
+                    return optionalAlbum.get().getImages();
+
+            } catch (Exception e) {
+                logger.error("[x] Failed to fetch images", e);
+            }
+            return new ArrayList<>();
+        }
+    };
+
+    /**
+     * Query for autocomplete predictions and bind them to the corresponding text field.
+     *
+     * @param keyEvent
+     */
+    public void queryAutocomplete(KeyEvent keyEvent) {
+        QueryAutocompleteRequest queryAutocompleteRequest = PlacesApi.queryAutocomplete(geoApiContext, address.get());
+
+        queryAutocompleteRequest.setCallback(new PendingResult.Callback<>() {
+            @Override
+            public void onResult(AutocompletePrediction[] autocompletePredictions) {
+                autoCompletions = Stream.of(autocompletePredictions)
+                        .map(prediction -> prediction.description)
+                        .collect(Collectors.toList());
+
+                TextFields.bindAutoCompletion(addressTextField,  autoCompletions);
+            }
+
+            @Override
+            public void onFailure(Throwable e) {
+                logger.error("[x] Failed to fetch predictions. Query='{}'", address.get(), e);
+            }
+        });
+    }
+
+    /**
+     * Search a Geocoding address with the current input in the address search text field.
+     * Centers the map on the first result.
+     *
+     * @param event
+     */
+    public void searchGeocodingAddress(ActionEvent event) {
+        GeocodingApiRequest geoCodingAddressRequest = GeocodingApi.newRequest(geoApiContext).address(address.get());
+
+        geoCodingAddressRequest.setCallback(new PendingResult.Callback<>() {
+            @Override
+            public void onResult(GeocodingResult[] result) {
+                LatLng firstLatLngFound = result[0].geometry.location;
+                logger.info("[x] Geocoding result found: {}", result[0].formattedAddress);
+
+                Platform.runLater(() -> centerMapOnLocation(firstLatLngFound));
+            }
+
+            @Override
+            public void onFailure(Throwable e) {
+                logger.error("[x] Failed to fetch Geocoding locations", e);
+                if (e instanceof ArrayIndexOutOfBoundsException)
+                    Platform.runLater(() -> showInfoAlert("No locations found"));
+                else
+                    Platform.runLater(() -> showInfoAlert("Oops, an error occurred while searching."));
+            }
+        });
+    }
+
+    /**
+     * Center map on given {@link LatLng} and set appropriate zoom level.
+     *
+     * @param latLng the location to center on
+     */
+    private void centerMapOnLocation(LatLng latLng) {
+        LatLong newLatLong = new LatLong(latLng.lat, latLng.lng);
+        googleMap.setCenter(newLatLong);
+        googleMap.setZoom(10);
+    }
+
+    /**
+     * Show an info alert to the user with given message.
+     *
+     * @param message the message containing info to the user
+     */
+    private void showInfoAlert(String message) {
+        Alert alert = new Alert(Alert.AlertType.INFORMATION, message);
+        alert.show();
+    }
+
+    /**
+     * Change scene to Main page.
+     * 
      * @param mouseEvent
      * @throws IOException
      */
@@ -131,7 +256,8 @@ public class Map implements Initializable, MapComponentInitializedListener {
 
     /**
      * Change scene to Search page. It reads the value of the search
-     * field and if not empty it is passed to dataexchange
+     * field and if not empty it is passed to dataexchange.
+     *
      * @param actionEvent
      * @throws IOException
      */
@@ -145,6 +271,7 @@ public class Map implements Initializable, MapComponentInitializedListener {
 
     /**
      * Change scene to Explore page
+     *
      * @param actionEvent
      * @throws IOException
      */
@@ -185,13 +312,5 @@ public class Map implements Initializable, MapComponentInitializedListener {
         App.setRoot("upload");
     }
 
-    /**
-     * Search for images on a specific place.
-     *
-     * @param actionEvent
-     */
-    public void MapSearch(ActionEvent actionEvent) {
-        //TODO: Make method
-    }
 }
 
diff --git a/src/main/java/NTNU/IDATT1002/database/EntityManagerConfig.java b/src/main/java/NTNU/IDATT1002/database/EntityManagerConfig.java
deleted file mode 100644
index 22d6059a579179ba1945809e05bb7c9fab33a5cc..0000000000000000000000000000000000000000
--- a/src/main/java/NTNU/IDATT1002/database/EntityManagerConfig.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package NTNU.IDATT1002.database;
-
-import org.hibernate.cfg.Environment;
-
-import javax.persistence.*;
-import java.util.*;
-
-
-/**
- * Entity Manager Configuration Singleton for overriding hibernate persistence properties.
- * Provides a single global access point to the applications entity manager.
- */
-public class EntityManagerConfig {
-
-    private static EntityManager entityManager;
-    private static Map<String, Object> configOverrides = new HashMap<>();
-    private static Properties properties = Environment.getProperties();
-
-
-    private EntityManagerConfig() {
-    }
-
-    /**
-     * Retrieve the entity manager instance.
-     * An entity manager is not created until it is requested.
-     *
-     * @return an entity manager instance
-     */
-    public static EntityManager getEntityManager() {
-        if (entityManager == null)
-            configureEntityManager();
-
-        return entityManager;
-    }
-
-    /**
-     * Parse properties and create the entity manager
-     */
-    private static void configureEntityManager() {
-        if (shouldOverrideConfig())
-            parseConfigProperties();
-
-        createEntityManager();
-    }
-
-    private static boolean shouldOverrideConfig() {
-        return Boolean.parseBoolean((String) properties.get("OVERRIDE_DEFAULT_DB_CONFIG"));
-    }
-
-    /**
-     * Parse properties from resources/hibernate.properties and overrides found values.
-     */
-    private static void parseConfigProperties() {
-        Set<Object> envKeys = properties.keySet();
-
-        for (Object key : envKeys)
-            parseProperty(key);
-    }
-
-    /**
-     * Parse desired values from given key in properties and add them to the configuration overrides.
-     *
-     * @param key the key to parse
-     */
-    private static void parseProperty(Object key) {
-        switch ((String) key) {
-            case "DB_DRIVER":
-                configOverrides.put("javax.persistence.jdbc.driver", properties.get(key));
-                break;
-            case "DB_URL":
-                configOverrides.put("javax.persistence.jdbc.url", properties.get(key));
-                break;
-            case "DB_USER":
-                configOverrides.put("javax.persistence.jdbc.user", properties.get(key));
-                break;
-            case "DB_PASSWORD":
-                configOverrides.put("javax.persistence.jdbc.password", properties.get(key));
-                break;
-            case "DB_DIALECT":
-                configOverrides.put("hibernate.dialect", properties.get(key));
-                break;
-            case "DB_HBM2DDL":
-                configOverrides.put("hibernate.hbm2ddl.auto", properties.get(key));
-                break;
-            default:
-                break;
-        }
-    }
-
-    /**
-     * Create an entity manager with configurations overrides.
-     */
-    private static void createEntityManager() {
-        EntityManagerFactory emf = Persistence.createEntityManagerFactory("ImageApplication", configOverrides);
-        entityManager = emf.createEntityManager();
-    }
-}
diff --git a/src/main/java/NTNU/IDATT1002/database/LoadDatabase.java b/src/main/java/NTNU/IDATT1002/database/LoadDatabase.java
index 4710eff43d08e72b0992e364dffb9b4f16106786..cff8693eefe5f16b79e202b2a04813f863ca7323 100644
--- a/src/main/java/NTNU/IDATT1002/database/LoadDatabase.java
+++ b/src/main/java/NTNU/IDATT1002/database/LoadDatabase.java
@@ -1,5 +1,6 @@
 package NTNU.IDATT1002.database;
 
+import NTNU.IDATT1002.Config;
 import NTNU.IDATT1002.models.Image;
 import NTNU.IDATT1002.models.Tag;
 import NTNU.IDATT1002.models.User;
@@ -24,7 +25,7 @@ public class LoadDatabase {
     private static ImageService imageService;
 
     static {
-        EntityManager entityManager = EntityManagerConfig.getEntityManager();
+        EntityManager entityManager = Config.getEntityManager();
 
         userService = new UserService(entityManager);
         albumService = new AlbumService(entityManager);
diff --git a/src/main/java/NTNU/IDATT1002/models/GeoLocation.java b/src/main/java/NTNU/IDATT1002/models/GeoLocation.java
index a52ad8319ed68788d6d43d0272e013cc178692a4..63f11c73a9f6e900cdb1d2f66608b0bcb6ea16ae 100644
--- a/src/main/java/NTNU/IDATT1002/models/GeoLocation.java
+++ b/src/main/java/NTNU/IDATT1002/models/GeoLocation.java
@@ -58,10 +58,6 @@ public class GeoLocation {
         return longitude;
     }
 
-    public void setGeoLocationId(Long geoLocationId) {
-        this.geoLocationId = geoLocationId;
-    }
-
     public void setLatitude(String altitude) {
         this.latitude = altitude;
     }
@@ -74,6 +70,15 @@ public class GeoLocation {
         this.metadata = metadata;
     }
 
+    /**
+     * Verify that this geolocation has latitude and longitude different from 0.
+     *
+     * @return whether latitude and longitude are different from 0.
+     */
+    public boolean hasLatLong() {
+        return Double.parseDouble(latitude) != 0 && Double.parseDouble(longitude) != 0;
+    }
+
     @Override
     public String toString() {
         return "GeoLocation{" +
diff --git a/src/main/java/NTNU/IDATT1002/service/UserService.java b/src/main/java/NTNU/IDATT1002/service/UserService.java
index 3bc5d4eabaad6533893edabb2517018a4b348245..532eadd4368ae9db065f07621de10f74e82f2e4a 100644
--- a/src/main/java/NTNU/IDATT1002/service/UserService.java
+++ b/src/main/java/NTNU/IDATT1002/service/UserService.java
@@ -7,10 +7,10 @@ import NTNU.IDATT1002.repository.LoginRepository;
 import NTNU.IDATT1002.repository.UserRepository;
 import NTNU.IDATT1002.utils.Authentication;
 
-import java.util.List;
 import javax.persistence.EntityManager;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.List;
 import java.util.Optional;
 
 /**
diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml
index 86ad1d585b7324862355d4a00296f010793ae399..7ff7ec019669b0df83a571d9d96a168d97873b8b 100644
--- a/src/main/resources/META-INF/persistence.xml
+++ b/src/main/resources/META-INF/persistence.xml
@@ -17,11 +17,6 @@
         <class>NTNU.IDATT1002.models.GeoLocation</class>
 
         <properties>
-            <!-- Configuring JDBC properties -->
-            <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver" />
-            <property name="javax.persistence.jdbc.url"    value="jdbc:mysql://mysql.stud.iie.ntnu.no:3306/g_sysutv_14" />
-            <property name="javax.persistence.jdbc.user" value="g_sysutv_14" />
-            <property name="javax.persistence.jdbc.password" value="tNdTRrwM" />
 
             <!-- Hibernate properties -->
             <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL8Dialect"/>
diff --git a/src/main/resources/NTNU/IDATT1002/map.fxml b/src/main/resources/NTNU/IDATT1002/map.fxml
index 8b71e37754e8d622c124b32dd2de2326fd77060d..994b816e731d40dab7670ac5f579cc373c926c54 100644
--- a/src/main/resources/NTNU/IDATT1002/map.fxml
+++ b/src/main/resources/NTNU/IDATT1002/map.fxml
@@ -61,12 +61,12 @@
                         <Font name="System Bold" size="24.0" />
                      </font>
                   </Text>
-                  <TextField fx:id="search" prefHeight="44.0" prefWidth="664.0" promptText="Search for your location">
+                  <TextField fx:id="addressTextField" onKeyPressed="#queryAutocomplete" onAction="#searchGeocodingAddress" prefHeight="44.0" prefWidth="664.0" promptText="Search for your location">
                      <font>
                         <Font size="18.0" />
                      </font>
                   </TextField>
-                  <Button fx:id="searchBtn" mnemonicParsing="false" onAction="#MapSearch" prefHeight="44.0" prefWidth="99.0" text="SEARCH">
+                  <Button fx:id="searchBtn" mnemonicParsing="false" onAction="#searchGeocodingAddress" prefHeight="44.0" prefWidth="99.0" text="GO">
                      <font>
                         <Font size="18.0" />
                      </font>
diff --git a/src/main/resources/hibernate.properties b/src/main/resources/hibernate.properties
deleted file mode 100644
index 1c3c5a0e157d86a48cb83f91363d52030ca119a5..0000000000000000000000000000000000000000
--- a/src/main/resources/hibernate.properties
+++ /dev/null
@@ -1,10 +0,0 @@
-# Set this value to true if you want to configure another connection
-OVERRIDE_DEFAULT_DB_CONFIG=false
-
-# These values correspond to database hosted on https://www.digitalocean.com/
-DB_DRIVER=com.mysql.cj.jdbc.Driver
-DB_URL=jdbc:mysql://db-mysql-lon1-07155-do-user-7212587-0.a.db.ondigitalocean.com:25060/image_application
-DB_USER=doadmin
-DB_PASSWORD=s4oxtqu20e8r7tx5
-DB_DIALECT=org.hibernate.dialect.MySQL8Dialect
-DB_HBM2DDL=update
\ No newline at end of file
diff --git a/src/test/resources/META-INF/persistence.xml b/src/test/resources/META-INF/persistence.xml
index 1292de038e0fa99c3a4fc9aacac92c969b8076f1..5275d466e056aec80d85aac13aa7f1d814a7923d 100644
--- a/src/test/resources/META-INF/persistence.xml
+++ b/src/test/resources/META-INF/persistence.xml
@@ -14,7 +14,6 @@
         <class>NTNU.IDATT1002.models.Album</class>
         <class>NTNU.IDATT1002.models.Metadata</class>
         <class>NTNU.IDATT1002.models.Tag</class>
-        <class>NTNU.IDATT1002.models.Histogram</class>
         <class>NTNU.IDATT1002.models.GeoLocation</class>
 
         <properties>