Index: trunk/src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java	(revision 8172)
+++ trunk/src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java	(revision 8174)
@@ -8,4 +8,5 @@
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
+import java.net.URL;
 import java.net.URLConnection;
 import java.util.HashSet;
@@ -126,14 +127,19 @@
     public void submit(ICachedLoaderListener listener) {
         boolean first = false;
-        String url = getUrl().toString();
-        if (url == null) {
+        URL url = getUrl();
+        String deduplicationKey = null;
+        if (url != null) {
+            // url might be null, for example when Bing Attribution is not loaded yet
+            deduplicationKey = url.toString();
+        }
+        if (deduplicationKey == null) {
             log.log(Level.WARNING, "No url returned for: {0}, skipping", getCacheKey());
             return;
         }
         synchronized (inProgress) {
-            Set<ICachedLoaderListener> newListeners = inProgress.get(url);
+            Set<ICachedLoaderListener> newListeners = inProgress.get(deduplicationKey);
             if (newListeners == null) {
                 newListeners = new HashSet<>();
-                inProgress.put(url, newListeners);
+                inProgress.put(deduplicationKey, newListeners);
                 first = true;
             }
@@ -162,5 +168,5 @@
 
     /**
-     * 
+     *
      * @return checks if object from cache has sufficient data to be returned
      */
@@ -171,5 +177,5 @@
 
     /**
-     * 
+     *
      * @return cache object as empty, regardless of what remote resource has returned (ex. based on headers)
      */
@@ -264,4 +270,8 @@
     }
 
+    /**
+     * @return true if object was successfully downloaded, false, if there was a loading failure
+     */
+
     private boolean loadObject() {
         try {
@@ -316,5 +326,5 @@
                             new Object[] {getCacheKey(), raw.length, getUrl()});
                     return true;
-                } else {
+                } else  {
                     cacheData = createCacheEntry(new byte[]{});
                     cache.put(getCacheKey(), cacheData, attributes);
@@ -326,6 +336,5 @@
             log.log(Level.FINE, "JCS - Caching empty object as server returned 404 for: {0}", getUrl());
             cache.put(getCacheKey(), createCacheEntry(new byte[]{}), attributes);
-            handleNotFound();
-            return true;
+            return handleNotFound();
         } catch (Exception e) {
             log.log(Level.WARNING, "JCS - Exception during download " + getUrl(), e);
@@ -336,5 +345,8 @@
     }
 
-    protected abstract void handleNotFound();
+    /**
+     *  @return if we should treat this object as properly loaded
+     */
+    protected abstract boolean handleNotFound();
 
     protected abstract V createCacheEntry(byte[] content);
Index: trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoader.java	(revision 8172)
+++ trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoader.java	(revision 8174)
@@ -19,5 +19,5 @@
 /**
  * @author Wiktor Niesiobędzki
- * 
+ *
  * Wrapper class that bridges between JCS cache and Tile Loaders
  *
@@ -73,5 +73,5 @@
     @Override
     public void addTile(Tile tile) {
-        createTileLoaderJob(tile).submit();
+        createTileLoaderJob(tile).getTile();
     }
 
Index: trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJob.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJob.java	(revision 8172)
+++ trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJob.java	(revision 8174)
@@ -125,5 +125,5 @@
             byte[] content = cacheData.getContent();
             try {
-                return (content != null && content.length > 0) || cacheData.getImage() != null || cacheAsEmpty();
+                return content != null  || cacheData.getImage() != null || cacheAsEmpty();
             } catch (IOException e) {
                 log.log(Level.WARNING, "JCS TMS - error loading from cache for tile {0}: {1}", new Object[] {tile.getKey(), e.getMessage()});
@@ -143,5 +143,5 @@
             return true;
         }
-        return false;
+        return false; // as there is no other cache to cache the Tile, also cache other empty requests
     }
 
@@ -159,5 +159,5 @@
     public void loadingFinished(CacheEntry object, boolean success) {
         try {
-            loadTile(object);
+            loadTile(object, success);
             if (listener != null) {
                 listener.tileLoadingFinished(tile, success);
@@ -178,5 +178,5 @@
      */
     public Tile getCachedTile() {
-        BufferedImageCacheEntry data = super.get();
+        BufferedImageCacheEntry data = get();
         if (isObjectLoadable()) {
             try {
@@ -193,5 +193,6 @@
     }
 
-    private void loadTile(CacheEntry object) throws IOException {
+    // loads tile when calling back from cache
+    private void loadTile(CacheEntry object, boolean success) throws IOException {
         tile.finishLoading();
         if (object != null) {
@@ -201,9 +202,13 @@
             }
         }
-    }
-
+        if (!success) {
+            tile.setError("Problem loading tile");
+        }
+    }
+
+    // loads tile when geting stright from cache
     private void loadTile(BufferedImageCacheEntry object) throws IOException {
         tile.finishLoading();
-        if (object != null) {
+        if (cacheAsEmpty() || object != null) { // if cache as empty object, do not try to load image
             if (object.getImage() != null) {
                 tile.setImage(object.getImage());
@@ -213,9 +218,15 @@
 
     @Override
-    protected void handleNotFound() {
+    protected boolean handleNotFound() {
         tile.setError("No tile at this zoom level");
         tile.putValue("tile-info", "no-tile");
-    }
-
+        return true;
+    }
+
+    /**
+     * For TMS use BaseURL as settings discovery, so for different paths, we will have different settings (useful for developer servers)
+     *
+     * @return base URL of TMS or server url as defined in super class
+     */
     @Override
     protected String getServerKey() {
