Datomic invalid connection config - clojure

I tried the following code to create a datomic database and connect to it:
(let [cfg (-> env :datomic-cfg)
client (d/client cfg)]
(do
(d/create-database
client
{:db-name "humboi-march-2021"})
(d/connect client {:db-name "humboi-march-2021"})))
However, I’m getting the following error:
Execution error (ExceptionInfo) at datomic.client.impl.pro/create-spi (pro.clj:72).
Invalid connection config: {:server-type :peer-server, :access-key "key-0680cb34675d5fd59", :secret "<ELIDED>", :endpoint "http://entry.humboi-2021.us-east-1.datomic.net:8182", :validate-hostnames false}
How to fix this?

Your uri has to be a string, for example I use:
(let [uri "datomic:free://localhost:4334/name"]
(d/create-database uri)
(d/connect uri))

Related

next.jdbc - unable to find valid certification path to requested target

The error
; Execution error (SunCertPathBuilderException) at
sun.security.provider.certpath.SunCertPathBuilder/build
(SunCertPathBuilder.java:141). ; unable to find valid certification
path to requested target
The code (Clojure)
(ns backend.core
(:require [next.jdbc :as jdbc]))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println "Hello, World!"))
(def db {:dbtype "sqlserver" :dbname "dbname" :user "MY_USER" :password "MY_PASSWORD" :host "MY_HOST" :port 1234})
(def datasource (jdbc/get-datasource db))
(defn create-product
"Create a product."
[name ds]
(jdbc/execute! ds [(str "insert into dbo.product (name) value('" name "')")]))
(comment
(create-product "my-product" datasource))
I'm playing around with clojure/sql server/next.jdbc and trying to work with my distant SQL Server 2017, but this error appear...
It look like I need some certificate. Is it the case? How can I generate it? How can I install it on my dev PC? Should it be install in a specific place?
I fixed my issue by changing the content of the (def db ...). Here is the updated code working.
(ns backend.core
(:require [next.jdbc :as jdbc]))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println "Hello, World!"))
(def db {:jdbcUrl "jdbc:sqlserver://MY_DISTANT_HOST:12345;databaseName=DB_NAME;user=USERNAME;password=MY_PASSWORD;encrypt=true;trustServerCertificate=true"})
(def datasource (jdbc/get-datasource db))
(defn create-product
"Create a product."
[name ds]
(with-open [connection (jdbc/get-connection ds)]
(jdbc/execute! connection ["insert into dbo.product (name) values (?)" name] {:return-keys true})))
(comment
(create-product "my-product" datasource))
You can find more information about jdbc connection string here: https://learn.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15
I too ran into a second issue after updating the data-source configuration. The error was:
no mssql-jdbc_auth-8.2.1.x64 in java.library.path
I only needed to download zip file here https://learn.microsoft.com/en-us/sql/connect/jdbc/download-microsoft-jdbc-driver-for-sql-server?view=sql-server-ver15, unzip it and follow instructions inside install.txt and finally restart my IDE (VS Code).

Clojure: How to restore REPL after exception?

What's the proper workflow in cases when you have an error after you restart/reload your app using mount?
An example:
user> (restart)
#error {
:cause "Unable to resolve symbol: account-database in this context"
:via
[{:type clojure.lang.Compiler$CompilerException
:message "Syntax error compiling at (app/model/session.clj:55:39)."
:data #:clojure.error{:phase :compile-syntax-check, :line 55, :column 39, :source "app/model/session.clj"}
:at [clojure.lang.Compiler analyze "Compiler.java" 6808]}
{:type java.lang.RuntimeException
:message "Unable to resolve symbol: account-database in this context"
:at [clojure.lang.Util runtimeException "Util.java" 221]}]
:trace
[[clojure.lang.Util runtimeException "Util.java" 221]
Reloadable Clojure REPL
user> (restart)
Syntax error compiling at (*cider-repl Projects/pollcro:localhost:43993(clj)*:597:7).
Unable to resolve symbol: restart in this context
user> (start)
Syntax error compiling at (*cider-repl Projects/pollcro:localhost:43993(clj)*:600:7).
Unable to resolve symbol: start in this context
After fixing an error, I can not (restart) this reply anymore due to the following error:
Unable to resolve symbol: restart in this context
Is it always like this or am I doing something wrong with my REPL workflow?
As a workaround, I cider-quit my REPL session and start it again but that's very annoying.
It seems I can use mount/start after fixing an error:
user> (mount/start)
{:started
["#'app.server-components.config/config"
"#'app.model.database/pool"
"#'app.model.mock-database/conn"]}
But it completely loses my user namespace scope, REPL doesn't see any of its methods + I can't send user namespace to repl because of the following error:
Syntax error compiling at (app/server_components/pathom.clj:1:1).
namespace 'app.model.session' not found
("src/main" "src/dev" "src/test")#function[expound.alpha/printer]nil#'user/start#'user/stop#'user/restartnil
That's what my user namespace looks like:
(ns user
(:require
[clojure.tools.namespace.repl :as tools-ns :refer [set-refresh-dirs]]
[expound.alpha :as expound]
[clojure.spec.alpha :as s]
[mount.core :as mount]
;; this is the top-level dependent component...mount will find the rest via ns requires
[app.server-components.http-server :refer [http-server]]))
;; ==================== SERVER ====================
(set-refresh-dirs "src/main" "src/dev" "src/test")
;; Change the default output of spec to be more readable
(alter-var-root #'s/*explain-out* (constantly expound/printer))
(defn start
"Start the web server"
[] (mount/start))
(defn stop
"Stop the web server"
[] (mount/stop))
(defn restart
"Stop, reload code, and restart the server. If there is a compile error, use:
(tools-ns/refresh)
to recompile, and then use `start` once things are good."
[]
(stop)
(tools-ns/refresh :after 'user/start))
Here's the workaround that seems to work in case of an error:
the content of a fixed file need to be sent to the REPL
switch back to user namespace
send the content of your user namespace to the REPL
there is no 4 - you just got your REPL back.
At this point you can use your regular (start), (stop), (restart).

No 'Access-Control-Allow-Origin' header is present when origin is allowed in Pedestal

When I try and request a resource from a cljs app (running on http://localhost:3000) to my Pedestal server (running on http://localhost:8080) I get the below error. I would like to allow CORS from http://localhost:3000:
XMLHttpRequest cannot load http://localhost:8080/db/query. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
I am using cljs-http to send the request from the client. The request looks something like this:
(defn load-server-data
[]
(go
(let [q (<! (http/post "http://localhost:8080/db/query"
{:edn-params {:query '[:find ?rep ?last
:where
[?rep :sales-rep/first-name ?last]]}}))]
(println "q" q))))
The route for /db/query looks like this:
(defroutes routes
[[["/db"
{:post handlers/db-post}
["/query" {:post handlers/db-query}
^:interceptors [interceptors/edn-interceptor]]]]])
This is the handler for /db/query:
(defn db-query
[req]
(let [edn-params (:edn-params req)
q (:query edn-params)
args (:args edn-params)
q-result (apply d/q q (d/db conn) args)]
{:status 200
:body (pr-str q-result)}))
To run the server I execute this function in the REPL.
(defn run-dev
"The entry-point for 'lein run-dev'"
[& args]
(println "\nCreating your [DEV] server...")
(-> service/service
(merge {:env :dev
::server/join? false
::server/routes #(deref #'service/routes)
::server/allowed-origins {:creds true :allowed-origins (constantly true)}})
server/default-interceptors
server/dev-interceptors
server/create-server
server/start))
There does not seem to be much information around CORS for Pedestal. I have looked at the cors example but it seems to just work while mine does not. Is there another interceptor I need to add to my routes or some sort of configuration setting that I am missing here?
I have figured out the problem. It turns out that an error was being thrown, however, it was getting swallowed and hidden from my debugger. Simply adding a try catch around my handler function fixes the problem.
(defn db-query
[req]
(try
(let [edn-params (:edn-params req)
q (:query edn-params)
args (:args edn-params)
q-result (apply d/q q (d/db conn) args)]
{:status 200
:body (pr-str q-result)})
(catch Exception ex
{:status 400
:body "Not authorized"})))
My original response:
The purpose of CORS is to limit the origin of the requests. You have
to purposely tell it where requests can come from. This will fix it.
(def service {;other config stuff
io.pedestal.http/allowed-origins ["http://localhost:3000"]}
It appears this is a duplicate question. Apparently javascript ajax requests are by definition limited to single origin. That code would work in production only if the GET request is made by clj-http or http-kit on the ring server that spawn http://localhost:3000 and then a cljs-http ajax request is made to that same ring server on port 3000. I still don't know why your run-dev doesn't work, but if you're calling lein with run, this is definitely what's happening.

how to connect to remote rabbitmq using clojure

I am using langohr to connect rabbitmq, if I don't specify any connection string, it works well and it connects to local server, but I want to connect to remote server. So I have the following code. I am using connection string of amqp://bigdata:bigdata#s1:5672, s2 is the hostname of the remote server.
let [ a (println rabbitmq-url)
rmq-conn (rmq/connect {:uri rabbitmq-url})
a (println rabbitmq-url)]
But it throws the error of the following
$ lein run
amqp://bigdata:bigdata#s1:5672
Exception in thread "main" java.io.IOException, compiling:(/tmp/form-init589039011205967992.clj:1:71)
at clojure.lang.Compiler.load(Compiler.java:7142)
at clojure.lang.Compiler.loadFile(Compiler.java:7086)
at clojure.main$load_script.invoke(main.clj:274)
at clojure.main$init_opt.invoke(main.clj:279)
at clojure.main$initialize.invoke(main.clj:307)
at clojure.main$null_opt.invoke(main.clj:342)
at clojure.main$main.doInvoke(main.clj:420)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:383)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Caused by: java.io.IOException
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:106)
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:102)
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:124)
at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:376)
at com.rabbitmq.client.impl.recovery.RecoveryAwareAMQConnectionFactory.newConnection(RecoveryAwareAMQConnectionFactory.java:36)
at com.rabbitmq.client.impl.recovery.AutorecoveringConnection.init(AutorecoveringConnection.java:83)
at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:609)
at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:651)
at com.novemberain.langohr.Connection.init(Connection.java:92)
at langohr.core$connect.invoke(core.clj:93)
at clojurewerkz.testcom.core$create_message_from_database.invoke(core.clj:33)
at clojurewerkz.testcom.core$create_message_from_database_loop.invoke(core.clj:53)
at clojurewerkz.testcom.core$_main.doInvoke(core.clj:60)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.Var.invoke(Var.java:375)
at user$eval5.invoke(form-init589039011205967992.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6703)
at clojure.lang.Compiler.eval(Compiler.java:6693)
at clojure.lang.Compiler.load(Compiler.java:7130)
... 11 more
Caused by: com.rabbitmq.client.ShutdownSignalException: connection error
at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:67)
at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:33)
at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:343)
at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:216)
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:118)
... 27 more
Caused by: java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:189)
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at java.io.DataInputStream.readUnsignedByte(DataInputStream.java:288)
at com.rabbitmq.client.impl.Frame.readFrom(Frame.java:95)
at com.rabbitmq.client.impl.SocketFrameHandler.readFrame(SocketFrameHandler.java:139)
at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:534)
at java.lang.Thread.run(Thread.java:745)
First, make sure that RabbitMQ is running on the remote server. Second, check if the user that is connecting to that instance has the permission to do so.
The same issue as below: my account doesn't have access to virtual hosts.
RabbitMQ new connection refused due to SocketException
try this code.
First, put these libs into your project.clj
;;rabbitmq client
[com.novemberain/langohr "2.11.0"]
;;logging
[org.clojure/tools.logging "0.2.4"]
Then, make necessary imports in your clj file:
(:require
;logging
[clojure.tools.logging :as log]
;;rabbitmq
[langohr.core :as rmq]
[langohr.channel :as lch]
[langohr.queue :as lq]
[langohr.exchange :as le]
[langohr.basic :as lb] ))
And here is connect function:
(defn get-mq-connect
"This function connects to RabbitMQ.
params example: {:host \"localhost\" :port 5672 :username \"guest\" :password \"guest\" :vhost \"/\"}
Returns: connect object - connection successful, nil - error occured."
[params]
(try
(log/trace params)
(rmq/connect params)
(catch Exception e
(log/error (.getMessage e))
(println "MQ connection error:" (.getMessage e)))))
You can call this function that way:
(let [ params {:host "myhost.com" :port 5672 :username "admin" :password "StrongPassw098" :vhost "/"}
conn (get-mq-connect mq-params)]
(when-not (nil? conn)
(let [ch (lch/open conn)]
(while (not #stop-flag?)
(do
;;put here your code
))
(rmq/close ch)
(rmq/close conn)))))

can't connect my compojure app to postgres db (following heroku tutorial)

i'm following along the heroku compojure tutorial. When I get to the point in the tutorial where a table is created, I get the following error message:
user=> (require '[clojure.java.jdbc :as sql])
nil
user=> (sql/with-connection (System/getenv "DATABASE_URL")
#_=> (sql/create-table :testing [:data :text]))
IllegalArgumentException db-spec postgresql://localhost:5432/lord is missing a required parameter clojure.java.jdbc.internal/get-connection (internal.clj:147)
I've tried adding the name of the linux user i created the db with and that users's password
to the DATABASE_URL but no luck. I'm missing something here and i'm not sure what it is. Where is db-spec defined might be the right question but i'm not exactly sure.
Try putting the connection into a map like this (this is mysql specific but you get the gist):
(def db-conn {
:classname "com.mysql.jdbc.Driver" ;must be in classpath
:subprotocol "mysql"
:subname (str "//" DBHOST ":" DBPORT "/" db-name)
; Any additional keys are passed to the driver as driver-specific properties.
:user DBUSER
:password DBPASS})
(sql/with-connection db-conn
(sql/create-table :testing [:data :text]))))
Hope this helps.