palletops / lein-uberimage

A Leiningen plugin to generate a docker image that runs a project's uberjar.
Eclipse Public License 1.0
136 stars 10 forks source link

lein uberimage fails with - No such var: clojure.core.cache/through #2

Closed vijaykiran closed 10 years ago

vijaykiran commented 10 years ago

Here's the shell history which reproduced the error:

➜ lein new app hello
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
Generating a project called hello based on the 'app' template.
➜  cd hello
➜  lein uberimage
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: No such var: clojure.core.cache/through, compiling:(clojure/core/memoize.clj:52:3)
 at clojure.lang.Compiler.analyze (Compiler.java:6464)
    clojure.lang.Compiler.analyze (Compiler.java:6406)
    clojure.lang.Compiler$InvokeExpr.parse (Compiler.java:3665)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6646)
    clojure.lang.Compiler.analyze (Compiler.java:6445)
    clojure.lang.Compiler.analyze (Compiler.java:6406)
    clojure.lang.Compiler$BodyExpr$Parser.parse (Compiler.java:5782)
    clojure.lang.Compiler$FnMethod.parse (Compiler.java:5217)
    clojure.lang.Compiler$FnExpr.parse (Compiler.java:3846)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6642)
    clojure.lang.Compiler.analyze (Compiler.java:6445)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6632)
    clojure.lang.Compiler.analyze (Compiler.java:6445)
    clojure.lang.Compiler.access$100 (Compiler.java:38)
    clojure.lang.Compiler$DefExpr$Parser.parse (Compiler.java:538)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6644)
    clojure.lang.Compiler.analyze (Compiler.java:6445)
    clojure.lang.Compiler.analyze (Compiler.java:6406)
    clojure.lang.Compiler.eval (Compiler.java:6707)
    clojure.lang.Compiler.load (Compiler.java:7130)
    clojure.lang.RT.loadResourceScript (RT.java:370)
    clojure.lang.RT.loadResourceScript (RT.java:361)
    clojure.lang.RT.load (RT.java:440)
    clojure.lang.RT.load (RT.java:411)
    clojure.core$load$fn__5066.invoke (core.clj:5641)
    clojure.core$load.doInvoke (core.clj:5640)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$load_one.invoke (core.clj:5446)
    clojure.core$load_lib$fn__5015.invoke (core.clj:5486)
    clojure.core$load_lib.doInvoke (core.clj:5485)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$load_libs.doInvoke (core.clj:5524)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$require.doInvoke (core.clj:5607)
    clojure.lang.RestFn.invoke (RestFn.java:436)
    clojure.tools.analyzer.jvm.utils$eval6310$loading__4958__auto____6311.invoke (utils.clj:9)
    clojure.tools.analyzer.jvm.utils$eval6310.invoke (utils.clj:9)
    clojure.lang.Compiler.eval (Compiler.java:6703)
    clojure.lang.Compiler.eval (Compiler.java:6692)
    clojure.lang.Compiler.load (Compiler.java:7130)
    clojure.lang.RT.loadResourceScript (RT.java:370)
    clojure.lang.RT.loadResourceScript (RT.java:361)
    clojure.lang.RT.load (RT.java:440)
    clojure.lang.RT.load (RT.java:411)
    clojure.core$load$fn__5066.invoke (core.clj:5641)
    clojure.core$load.doInvoke (core.clj:5640)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$load_one.invoke (core.clj:5446)
    clojure.core$load_lib$fn__5015.invoke (core.clj:5486)
    clojure.core$load_lib.doInvoke (core.clj:5485)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$load_libs.doInvoke (core.clj:5524)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$require.doInvoke (core.clj:5607)
    clojure.lang.RestFn.invoke (RestFn.java:512)
    clojure.tools.analyzer.jvm$eval6304$loading__4958__auto____6305.invoke (jvm.clj:9)
    clojure.tools.analyzer.jvm$eval6304.invoke (jvm.clj:9)
    clojure.lang.Compiler.eval (Compiler.java:6703)
    clojure.lang.Compiler.eval (Compiler.java:6692)
    clojure.lang.Compiler.load (Compiler.java:7130)
    clojure.lang.RT.loadResourceScript (RT.java:370)
    clojure.lang.RT.loadResourceScript (RT.java:361)
    clojure.lang.RT.load (RT.java:440)
    clojure.lang.RT.load (RT.java:411)
    clojure.core$load$fn__5066.invoke (core.clj:5641)
    clojure.core$load.doInvoke (core.clj:5640)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$load_one.invoke (core.clj:5446)
    clojure.core$load_lib$fn__5015.invoke (core.clj:5486)
    clojure.core$load_lib.doInvoke (core.clj:5485)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$load_libs.doInvoke (core.clj:5524)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$require.doInvoke (core.clj:5607)
    clojure.lang.RestFn.invoke (RestFn.java:551)
    clojure.core.async.impl.ioc_macros$eval5899$loading__4958__auto____5900.invoke (ioc_macros.clj:12)
    clojure.core.async.impl.ioc_macros$eval5899.invoke (ioc_macros.clj:12)
    clojure.lang.Compiler.eval (Compiler.java:6703)
    clojure.lang.Compiler.eval (Compiler.java:6692)
    clojure.lang.Compiler.load (Compiler.java:7130)
    clojure.lang.RT.loadResourceScript (RT.java:370)
    clojure.lang.RT.loadResourceScript (RT.java:361)
    clojure.lang.RT.load (RT.java:440)
    clojure.lang.RT.load (RT.java:411)
    clojure.core$load$fn__5066.invoke (core.clj:5641)
    clojure.core$load.doInvoke (core.clj:5640)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$load_one.invoke (core.clj:5446)
    clojure.core$load_lib$fn__5015.invoke (core.clj:5486)
    clojure.core$load_lib.doInvoke (core.clj:5485)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$load_libs.doInvoke (core.clj:5524)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$require.doInvoke (core.clj:5607)
    clojure.lang.RestFn.invoke (RestFn.java:619)
    clojure.core.async$eval5419$loading__4958__auto____5420.invoke (async.clj:9)
    clojure.core.async$eval5419.invoke (async.clj:9)
    clojure.lang.Compiler.eval (Compiler.java:6703)
    clojure.lang.Compiler.eval (Compiler.java:6692)
    clojure.lang.Compiler.load (Compiler.java:7130)
    clojure.lang.RT.loadResourceScript (RT.java:370)
    clojure.lang.RT.loadResourceScript (RT.java:361)
    clojure.lang.RT.load (RT.java:440)
    clojure.lang.RT.load (RT.java:411)
    clojure.core$load$fn__5066.invoke (core.clj:5641)
    clojure.core$load.doInvoke (core.clj:5640)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$load_one.invoke (core.clj:5446)
    clojure.core$load_lib$fn__5015.invoke (core.clj:5486)
    clojure.core$load_lib.doInvoke (core.clj:5485)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$load_libs.doInvoke (core.clj:5524)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$require.doInvoke (core.clj:5607)
    clojure.lang.RestFn.invoke (RestFn.java:930)
    leiningen.uberimage$eval5413$loading__4958__auto____5414.invoke (uberimage.clj:1)
    leiningen.uberimage$eval5413.invoke (uberimage.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:6703)
    clojure.lang.Compiler.eval (Compiler.java:6692)
    clojure.lang.Compiler.load (Compiler.java:7130)
    clojure.lang.RT.loadResourceScript (RT.java:370)
    clojure.lang.RT.loadResourceScript (RT.java:361)
    clojure.lang.RT.load (RT.java:440)
    clojure.lang.RT.load (RT.java:411)
    clojure.core$load$fn__5066.invoke (core.clj:5641)
    clojure.core$load.doInvoke (core.clj:5640)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$load_one.invoke (core.clj:5446)
    clojure.core$load_lib$fn__5015.invoke (core.clj:5486)
    clojure.core$load_lib.doInvoke (core.clj:5485)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$load_libs.doInvoke (core.clj:5524)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$require.doInvoke (core.clj:5607)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    leiningen.core.utils$require_resolve.invoke (utils.clj:68)
    leiningen.core.utils$require_resolve.invoke (utils.clj:71)
    leiningen.core.main$lookup_task_var.invoke (main.clj:48)
    leiningen.core.main$pass_through_help_QMARK_.invoke (main.clj:55)
    leiningen.core.main$task_args.invoke (main.clj:58)
    leiningen.core.main$resolve_and_apply.invoke (main.clj:295)
    leiningen.core.main$_main$fn__5979.invoke (main.clj:366)
    leiningen.core.main$_main.doInvoke (main.clj:353)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.lang.Var.invoke (Var.java:379)
    clojure.lang.AFn.applyToHelper (AFn.java:154)
    clojure.lang.Var.applyTo (Var.java:700)
    clojure.core$apply.invoke (core.clj:624)
    clojure.main$main_opt.invoke (main.clj:315)
    clojure.main$main.doInvoke (main.clj:420)
    clojure.lang.RestFn.invoke (RestFn.java:436)
    clojure.lang.Var.invoke (Var.java:388)
    clojure.lang.AFn.applyToHelper (AFn.java:160)
    clojure.lang.Var.applyTo (Var.java:700)
    clojure.main.main (main.java:37)
Caused by: java.lang.RuntimeException: No such var: clojure.core.cache/through
 at clojure.lang.Util.runtimeException (Util.java:221)
    clojure.lang.Compiler.resolveIn (Compiler.java:6914)
    clojure.lang.Compiler.resolve (Compiler.java:6884)
    clojure.lang.Compiler.analyzeSymbol (Compiler.java:6845)
    clojure.lang.Compiler.analyze (Compiler.java:6427)
    clojure.lang.Compiler.analyze (Compiler.java:6406)
    clojure.lang.Compiler$InvokeExpr.parse (Compiler.java:3665)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6646)
    clojure.lang.Compiler.analyze (Compiler.java:6445)
    clojure.lang.Compiler.analyze (Compiler.java:6406)
    clojure.lang.Compiler$BodyExpr$Parser.parse (Compiler.java:5782)
    clojure.lang.Compiler$FnMethod.parse (Compiler.java:5217)
    clojure.lang.Compiler$FnExpr.parse (Compiler.java:3846)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6642)
    clojure.lang.Compiler.analyze (Compiler.java:6445)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6632)
    clojure.lang.Compiler.analyze (Compiler.java:6445)
    clojure.lang.Compiler.access$100 (Compiler.java:38)
    clojure.lang.Compiler$DefExpr$Parser.parse (Compiler.java:538)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6644)
    clojure.lang.Compiler.analyze (Compiler.java:6445)
    clojure.lang.Compiler.analyze (Compiler.java:6406)
    clojure.lang.Compiler.eval (Compiler.java:6707)
    clojure.lang.Compiler.load (Compiler.java:7130)
    clojure.lang.RT.loadResourceScript (RT.java:370)
    clojure.lang.RT.loadResourceScript (RT.java:361)
    clojure.lang.RT.load (RT.java:440)
    clojure.lang.RT.load (RT.java:411)
    clojure.core$load$fn__5066.invoke (core.clj:5641)
    clojure.core$load.doInvoke (core.clj:5640)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$load_one.invoke (core.clj:5446)
    clojure.core$load_lib$fn__5015.invoke (core.clj:5486)
    clojure.core$load_lib.doInvoke (core.clj:5485)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$load_libs.doInvoke (core.clj:5524)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$require.doInvoke (core.clj:5607)
    clojure.lang.RestFn.invoke (RestFn.java:436)
    clojure.tools.analyzer.jvm.utils$eval6310$loading__4958__auto____6311.invoke (utils.clj:9)
    clojure.tools.analyzer.jvm.utils$eval6310.invoke (utils.clj:9)
    clojure.lang.Compiler.eval (Compiler.java:6703)
    clojure.lang.Compiler.eval (Compiler.java:6692)
    clojure.lang.Compiler.load (Compiler.java:7130)
    clojure.lang.RT.loadResourceScript (RT.java:370)
    clojure.lang.RT.loadResourceScript (RT.java:361)
    clojure.lang.RT.load (RT.java:440)
    clojure.lang.RT.load (RT.java:411)
    clojure.core$load$fn__5066.invoke (core.clj:5641)
    clojure.core$load.doInvoke (core.clj:5640)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$load_one.invoke (core.clj:5446)
    clojure.core$load_lib$fn__5015.invoke (core.clj:5486)
    clojure.core$load_lib.doInvoke (core.clj:5485)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$load_libs.doInvoke (core.clj:5524)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$require.doInvoke (core.clj:5607)
    clojure.lang.RestFn.invoke (RestFn.java:512)
    clojure.tools.analyzer.jvm$eval6304$loading__4958__auto____6305.invoke (jvm.clj:9)
    clojure.tools.analyzer.jvm$eval6304.invoke (jvm.clj:9)
    clojure.lang.Compiler.eval (Compiler.java:6703)
    clojure.lang.Compiler.eval (Compiler.java:6692)
    clojure.lang.Compiler.load (Compiler.java:7130)
    clojure.lang.RT.loadResourceScript (RT.java:370)
    clojure.lang.RT.loadResourceScript (RT.java:361)
    clojure.lang.RT.load (RT.java:440)
    clojure.lang.RT.load (RT.java:411)
    clojure.core$load$fn__5066.invoke (core.clj:5641)
    clojure.core$load.doInvoke (core.clj:5640)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$load_one.invoke (core.clj:5446)
    clojure.core$load_lib$fn__5015.invoke (core.clj:5486)
    clojure.core$load_lib.doInvoke (core.clj:5485)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$load_libs.doInvoke (core.clj:5524)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$require.doInvoke (core.clj:5607)
    clojure.lang.RestFn.invoke (RestFn.java:551)
    clojure.core.async.impl.ioc_macros$eval5899$loading__4958__auto____5900.invoke (ioc_macros.clj:12)
    clojure.core.async.impl.ioc_macros$eval5899.invoke (ioc_macros.clj:12)
    clojure.lang.Compiler.eval (Compiler.java:6703)
    clojure.lang.Compiler.eval (Compiler.java:6692)
    clojure.lang.Compiler.load (Compiler.java:7130)
    clojure.lang.RT.loadResourceScript (RT.java:370)
    clojure.lang.RT.loadResourceScript (RT.java:361)
    clojure.lang.RT.load (RT.java:440)
    clojure.lang.RT.load (RT.java:411)
    clojure.core$load$fn__5066.invoke (core.clj:5641)
    clojure.core$load.doInvoke (core.clj:5640)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$load_one.invoke (core.clj:5446)
    clojure.core$load_lib$fn__5015.invoke (core.clj:5486)
    clojure.core$load_lib.doInvoke (core.clj:5485)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$load_libs.doInvoke (core.clj:5524)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$require.doInvoke (core.clj:5607)
    clojure.lang.RestFn.invoke (RestFn.java:619)
    clojure.core.async$eval5419$loading__4958__auto____5420.invoke (async.clj:9)
    clojure.core.async$eval5419.invoke (async.clj:9)
    clojure.lang.Compiler.eval (Compiler.java:6703)
    clojure.lang.Compiler.eval (Compiler.java:6692)
    clojure.lang.Compiler.load (Compiler.java:7130)
    clojure.lang.RT.loadResourceScript (RT.java:370)
    clojure.lang.RT.loadResourceScript (RT.java:361)
    clojure.lang.RT.load (RT.java:440)
    clojure.lang.RT.load (RT.java:411)
    clojure.core$load$fn__5066.invoke (core.clj:5641)
    clojure.core$load.doInvoke (core.clj:5640)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$load_one.invoke (core.clj:5446)
    clojure.core$load_lib$fn__5015.invoke (core.clj:5486)
    clojure.core$load_lib.doInvoke (core.clj:5485)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$load_libs.doInvoke (core.clj:5524)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$require.doInvoke (core.clj:5607)
    clojure.lang.RestFn.invoke (RestFn.java:930)
    leiningen.uberimage$eval5413$loading__4958__auto____5414.invoke (uberimage.clj:1)
    leiningen.uberimage$eval5413.invoke (uberimage.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:6703)
    clojure.lang.Compiler.eval (Compiler.java:6692)
    clojure.lang.Compiler.load (Compiler.java:7130)
    clojure.lang.RT.loadResourceScript (RT.java:370)
    clojure.lang.RT.loadResourceScript (RT.java:361)
    clojure.lang.RT.load (RT.java:440)
    clojure.lang.RT.load (RT.java:411)
    clojure.core$load$fn__5066.invoke (core.clj:5641)
    clojure.core$load.doInvoke (core.clj:5640)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$load_one.invoke (core.clj:5446)
    clojure.core$load_lib$fn__5015.invoke (core.clj:5486)
    clojure.core$load_lib.doInvoke (core.clj:5485)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$load_libs.doInvoke (core.clj:5524)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$require.doInvoke (core.clj:5607)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    leiningen.core.utils$require_resolve.invoke (utils.clj:68)
    leiningen.core.utils$require_resolve.invoke (utils.clj:71)
    leiningen.core.main$lookup_task_var.invoke (main.clj:48)
    leiningen.core.main$pass_through_help_QMARK_.invoke (main.clj:55)
    leiningen.core.main$task_args.invoke (main.clj:58)
    leiningen.core.main$resolve_and_apply.invoke (main.clj:295)
    leiningen.core.main$_main$fn__5979.invoke (main.clj:366)
    leiningen.core.main$_main.doInvoke (main.clj:353)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.lang.Var.invoke (Var.java:379)
    clojure.lang.AFn.applyToHelper (AFn.java:154)
    clojure.lang.Var.applyTo (Var.java:700)
    clojure.core$apply.invoke (core.clj:624)
    clojure.main$main_opt.invoke (main.clj:315)
    clojure.main$main.doInvoke (main.clj:420)
    clojure.lang.RestFn.invoke (RestFn.java:436)
    clojure.lang.Var.invoke (Var.java:388)
    clojure.lang.AFn.applyToHelper (AFn.java:160)
    clojure.lang.Var.applyTo (Var.java:700)
    clojure.main.main (main.java:37)
hugoduncan commented 10 years ago

Could you try with:

LEIN_NO_USER_PROFILES=1 lein uberimage
vijaykiran commented 10 years ago

@hugoduncan I removed uberimage from ~/.lein/profiles.clj (just to be sure) and added to the newly created project:

(defproject hello "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.6.0"]]
  :main ^:skip-aot hello.core
  :target-path "target/%s"
  :plugins  [[com.palletops/uberimage "0.1.2"]]
  :profiles {:uberjar {:aot :all}})

Here is what I get now:

➜  LEIN_NO_USER_PROFILES=1 lein uberimage
Created /Users/vijaykiran/tmp/hello/target/uberjar/hello-0.1.0-SNAPSHOT.jar
Created /Users/vijaykiran/tmp/hello/target/uberjar/hello-0.1.0-SNAPSHOT-standalone.jar
Using jar file /Users/vijaykiran/tmp/hello/target/hello-0.1.0-SNAPSHOT-standalone.jar
Jar file does not exist

FYI - The exception (No such var) only occurs when using uberimage in profiles.clj - so I think there might be some conflict among the plugins I'm using.

hugoduncan commented 10 years ago

Something with the %s in the :target-path is confusing the plugin. If you remove that line from your project.clj, everything should be fine.

vijaykiran commented 10 years ago

Thanks - removing target-path and using LEIN_NO_USER_PROFILES=1 lein uberimage helped.