DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

The Latest Popular Topics

article thumbnail
Easily Update and Reload SSL for a Server and an HTTP Client
In this tutorial, learn how to update and reload your SSL configuration whenever needed without restarting your server or recreating your HTTP client.
October 4, 2022
by Hakan Altındağ
· 11,125 Views · 4 Likes
article thumbnail
Value Stream Management Meets Engineering Analytics
Let's dive into The State of Value Stream Management Report 2022 and its lessons for software and platform engineering teams.
October 4, 2022
by Ralf Huuck
· 4,888 Views · 3 Likes
article thumbnail
Inspect the Contents of the Java Metaspace Region
Learn more about JVM and how to inspect the contents of the Java Metaspace region.
October 3, 2022
by Ram Lakshmanan DZone Core CORE
· 8,472 Views · 1 Like
article thumbnail
How To Validate Names Using Java
Gain context of three separate API solutions which can be used to validate name input fields within an application as you follow along with this demonstration.
October 3, 2022
by Brian O'Neill DZone Core CORE
· 8,991 Views · 4 Likes
article thumbnail
Top Posts of 2013: 10 Subtle Best Practices when Coding Java
This list here contains less common situations involving API / SPI design that many Java articles do not cover.
October 3, 2022
by Lukas Eder
· 123,964 Views · 1 Like
article thumbnail
10 More Common Mistakes Java Developers Make when Writing SQL
i was positively surprised to see how popular my recent listing about 10 common mistakes java developers make when writing sql was, both on my own blog and on my syndication partner dzone . the popularity shows a couple of things: how important sql is to the professional java world. how common it is to forget about some basic sql things. how well sql-centric libraries such as jooq or mybatis are responding to market needs, by embracing sql . an amusing fact is that users have even mentioned my blog post on slick’s mailing list . slick is a non-sql-centric database access library in scala. like linq (and linq-to-sql) it focuses on language integration , not on sql code generation. anyway, the common mistakes i listed previously are far from complete, so i will treat you to a sequel of 10 subtly less common, yet equally interesting mistakes java developers make when writing sql. 1. not using preparedstatements interestingly, this mistake or misbelief still surfaces blogs , forums and mailing lists many years after the appearance of jdbc, even if it is about a very simple thing to remember and to understand. it appears that some developers refrain from using preparedstatements for any of these reasons: they don’t know about preparedstatements they think that preparedstatements are slower they think that writing a preparedstatement takes more effort first off, let’s bust the above myths. in 96% of the cases, you’re better off writing a preparedstatement rather than a static statement. why? for simple reasons: you can omit syntax errors originating from bad string concatenation when inlining bind values. you can omit sql injection vulnerabilities from bad string concatenation when inlining bind values. you can avoid edge-cases when inlining more “sophisticated” data types, such as timestamp, binary data, and others. you can keep open preparedstatements around for a while, reusing them with new bind values instead of closing them immediately (useful in postgres, for instance). you can make use of adaptive cursor sharing (oracle-speak) in more sophisticated databases. this helps prevent hard-parsing sql statements for every new set of bind values. convinced? yes. note, there are some rare cases when you actually want to inline bind values in order to give your database’s cost-based optimiser some heads-up about what kind of data is really going to be affected by the query. typically, this results in “constant” predicates such as: deleted = 1 status = 42 but it shouldn’t result in “variable” predicates such as: first_name like “jon%” amount > 19.95 note that modern databases implement bind-variable peeking. hence, by default, you might as well use bind values for all your query parameters. note also that higher-level apis such as jpa criteriaquery or jooq will help you generate preparedstatements and bind values very easily and transparently when writing embedded jpql or embedded sql. more background info: caveats of bind value peeking: an interesting blog post by oracle guru tanel poder on the subject cursor sharing. an interesting stack overflow question . the cure : by default, always use preparedstatements instead of static statements. by default, never inline bind values into your sql. 2. returning too many columns this mistake is quite frequent and can lead to very bad effects both in your database’s execution plan and in your java application. let’s look at the second effect first: bad effects on the java application: if you’re selecting * (star) or a “default” set of 50 columns, which you’re reusing among various daos, you’re transferring lots of data from the database into a jdbc resultset. even if you’re not reading the data from the resultset, it has been transferred over the wire and loaded into your memory by the jdbc driver. that’s quite a waste of io and memory if you know that you’re only going to need 2-3 of those columns. this was obvious, but beware also of… bad effects on the database execution plan: these effects may actually be much worse than the effects on the java application. sophisticated databases perform a lot of sql transformation when calculating the best execution plan for your query. it may well be that some parts of your query can be “transformed away”, knowing that they won’t contribute to the projection (select clause) or to the filtering predicates. i’ve recently blogged about this in the context of schema meta data: how schema meta data impacts oracle query transformations now, this is quite a beast. think about a sophisticated select that will join two views: select * from customer_view c join order_view o on c.cust_id = o.cust_id each of the views that are joined to the above joined table reference might again join data from dozens of tables, such as customer_address, order_history, order_settlement, etc. given the select * projection, your database has no choice but to fully perform the loading of all those joined tables, when in fact, the only thing that you were interested in was this: select c.first_name, c.last_name, o.amount from customer_view c join order_view o on c.cust_id = o.cust_id a good database will transform your sql in a way that most of the “hidden” joins can be removed, which results in much less io and memory consumption within the database. the cure : never execute select *. never reuse the same projection for various queries. always try to reduce the projection to the data that you really need. note that this can be quite hard to achieve with orms. 3. thinking that join is a select clause this isn’t a mistake with a lot of impact on performance or sql correctness, but nevertheless, sql developers should be aware of the fact that the join clause is not part of the select statement per se. the sql standard 1992 defines a table reference as such: 6.3 ::= [ [ as ] [ ] ] | [ as ] [ ] | the from clause and also the joined table can then make use of such table references : 7.4 ::= from [ { }... ] 7.5 ::= | | ::= cross join ::= [ natural ] [ ] join [ ] relational databases are very table-centric. many operations are performed on physical, joined or derived tables in one way or another. to write sql effectively, it is important to understand that the select .. from clause expects a comma-separated list of table references in whatever form they may be provided. depending on the complexity of the table reference, some databases also accept sophisticated table references in other statements, such as insert, update, delete, merge. see oracle’s manuals for instance , explaining how to create updatable views. the cure : always think of your from clause to expect a table reference as a whole. if you write a join clause, think of this join clause to be part of a complex table reference: select c.first_name, c.last_name, o.amount from customer_view c join order_view o on c.cust_id = o.cust_id 4. using pre-ansi join syntax now that we’ve clarified how table references work (see the previous point), it should become a bit more obvious that the pre-ansi join syntax should be avoided at all costs. to execution plans, it usually makes no difference if you specify join predicates in the join .. on clause or in the where clause. but from a readability and maintenance perspective, using the where clause for both filtering predicates and join predicates is a major quagmire. consider this simple example: select c.first_name, c.last_name, o.amount from customer_view c, order_view o where o.amount > 100 and c.cust_id = o.cust_id and c.language = 'en' can you spot the join predicate? what if we joined dozens of tables? this gets much worse when applying proprietary syntaxes for outer join, such as oracle’s (+) syntax . the cure : always use the ansi join syntax. never put join predicates into the where clause. there is absolutely no advantage to using the pre-ansi join syntax. 5. forgetting to escape input to the like predicate the sql standard 1992 specifies the like predicate as such: 8.5 ::= [ not ] like [ escape ] the escape keyword should be used almost always when allowing for user input to be used in your sql queries. while it may be rare that the percent sign (%) is actually supposed to be part of the data, the underscore (_) might well be: select * from t where t.x like 'some!_prefix%' escape '!' the cure : always think of proper escaping when using the like predicate. 6. thinking that not (a in (x, y)) is the boolean inverse of a in (x, y) this one is subtle but very important with respect to nulls! let’s review what a in (x, y) really means: a in (x, y) is the same as a = any (x, y) is the same as a = x or a = y when at the same time, not (a in (x, y)) really means: not (a in (x, y)) is the same as a not in (x, y) is the same as a != any (x, y) is the same as a != x and a != y that looks like the boolean inverse of the previous predicate, but it isn’t! if any of x or y is null , the not in predicate will result in unknown whereas the in predicate might still return a boolean value. or in other words, when a in (x, y) yields true or false , not(a in (x, y)) may still yield unknown instead of false or true . note, that this is also true if the right-hand side of the in predicate is a subquery. don’t believe it? see this sql fiddle for yourself. it shows that the following query yields no result: select 1 where 1 in (null) union all select 2 where not(1 in (null)) more details can be seen in my previous blog post on that subject , which also shows some sql dialect incompatibilities in that area. the cure : beware of the not in predicate when nullable columns are involved! 7. thinking that not (a is null) is the same as a is not null right, so we remembered that sql implements three-valued logic when it comes to handling null. that’s why we can use the null predicate to check for null values. right? right. but even the null predicate is subtle. beware that the two following predicates are only equivalent for row value expressions of degree 1: not (a is null) is not the same as a is not null if a is a row value expression with a degree of more than 1, then the truth table is transformed such that: a is null yields true only if all values in a are null not(a is null) yields false only if all values in a are null a is not null yields true only if all values in a are not null not(a is not null) yields false only if all values in a are not null see more details in my previous blog post on that subject . the cure : when using row value expressions, beware of the null predicate, which might not work as expected. 8. not using row value expressions where they are supported row value expressions are an awesome sql feature. when sql is a very table-centric language, tables are also very row-centric. row value expressions let you describe complex predicates much more easily, by creating local ad-hoc rows that can be compared with other rows of the same degree and row type. a simple example is to query customers for first names and last names at the same time. select c.address from customer c, where (c.first_name, c.last_name) = (?, ?) as can be seen, this syntax is slightly more concise than the equivalent syntax where each column from the predicate’s left-hand side is compared with the corresponding column on the right-hand side. this is particularly true if many independent predicates are combined with and. using row value expressions allows you to combine correlated predicates into one. this is most useful for join expressions on composite foreign keys: select c.first_name, c.last_name, a.street from customer c join address a on (c.id, c.tenant_id) = (a.id, a.tenant_id) unfortunately, not all databases support row value expressions in the same way. but the sql standard had defined them already in 1992 , and if you use them, sophisticated databases like oracle or postgres can use them for calculating better execution plans. this is explained on the popular use the index, luke page. the cure : use row value expressions whenever you can. they will make your sql more concise and possibly even faster. 9. not defining enough constraints so, i’m going to cite tom kyte and use the index, luke again. you cannot have enough constraints in your meta data. first off, constraints help you keep your data from corrupting, which is already very useful. but to me, more importantly, constraints will help the database perform sql transformations, as the database can decide that some values are equivalent some clauses are redundant some clauses are “void” (i.e. they will not return any values) some developers may think that constraints are slow. the opposite is the case, unless you insert lots and lots of data, in case of which you can either disable constraints for a large operation, or use a temporary “load table” without constraints, transferring data offline to the real table. the cure : define as many constraints as you can. they will help your database to perform better when querying. 10. thinking that 50ms is fast query execution the nosql hype is still ongoing, and many companies still think they’re twitter or facebook in dire need of faster, more scalable solutions, escaping acid and relational models to scale horizontally. some may succeed (e.g. twitter or facebook), others may run into this: found here: https://twitter.com/codinghorror/status/347070841059692545 for the others who are forced (or chose) to stick with proven relational databases, don’t be tricked into thinking that modern databases are slow. they’re hyper fast. in fact, they’re so fast, they can parse your 20kb query text, calculate 2000-line execution plans, and actually execute that monster in less than a millisecond, if you and your dba get along well and tune your database to the max. they may be slow because of your application misusing a popular orm , or because that orm won’t be able to produce fast sql for your complex querying logic. in that case, you may want to chose a more sql-centric api like jdbc , jooq or mybatis that will let you get back in control of your sql. so, don’t think that a query execution of 50ms is fast or even acceptable. it’s not. if you get these speeds at development time, make sure you investigate execution plans. those monsters might explode in production, where you have more complex contexts and data. conclusion sql is a lot of fun, but also very subtle in various ways. it’s not easy to get it right as my previous blog post about 10 common mistakes has shown. but sql can be mastered and it’s worth the trouble. data is your most valuable asset. treat data with respect and write better sql.
October 3, 2022
by Lukas Eder
· 38,095 Views · 3 Likes
article thumbnail
Improve Your Application's Serialization Through Efficient Object Marshaling
Demonstrating how to encode small Strings into long primitives using object marshaling examples and how to improve the performance of your app’s serialization.
September 30, 2022
by Jasmine Taylor
· 9,079 Views · 11 Likes
article thumbnail
Creating a Box and Whiskers Chart With TypeScript and LightningChart JS
Learn how to create a fully customizable box and whiskers chart in Visual Studio Code using TypeScript, NodeJS, and LightningChart JS charting library.
Updated September 30, 2022
by LightningChart LightningChart
· 4,087 Views · 1 Like
article thumbnail
What a Healthy Relationship With Open Source Looks Like Ft. Gitlab’s John Coghlan
Almost everyone uses open source, but how do they contribute to it? John joins Dan Lines on this episode of Dev Interrupted to talk about making devs' lives better
September 29, 2022
by Dan Lines
· 5,771 Views · 1 Like
article thumbnail
How to Use Hugging Face Models for NLP, Audio Classification, and Computer Vision
When using Hugging Face for NLP, audio classification, or computer vision, users need to know what Hugging Face offers for each project type.
September 29, 2022
by Kevin Vu
· 8,148 Views · 1 Like
article thumbnail
How the World Caught up With Apache Cassandra
Learn more about Apache Cassandra and how to make it effective.
Updated September 28, 2022
by Jeffrey Carpenter
· 5,185 Views · 2 Likes
article thumbnail
What Is Web 3.0 and Why It’s Important
What is Web 3.0 how it's different from the current version of the Web? What are its benefits and drawbacks, when it arrives if ever?
September 28, 2022
by Pavel Terenin
· 6,836 Views · 2 Likes
article thumbnail
Palindrome Program in Java
An Introduction to the Palindrome and how Palindrome Program is used in Java is described using different approaches and gives solutions to the problems.
September 28, 2022
by Alisha Singh
· 14,483 Views · 2 Likes
article thumbnail
The Reason Java Is Still Popular
There's a reason Java maintained popularity for such a long period of time. Its conservative, slow and steady approach is the key to its success.
September 28, 2022
by Shai Almog DZone Core CORE
· 15,847 Views · 18 Likes
article thumbnail
Build Your Own Social Media Analytics with Apache Kafka
Stream messages between API endpoints using Kafka running on Kubernetes.
September 28, 2022
by Sylvain Kalache
· 5,271 Views · 1 Like
article thumbnail
Java and Low Latency
It's possible to build Java applications that satisfy very stringent requirements in terms of their response times to external events, but it does require some careful thought. This article discusses the sort of things that need to be considered when developing low latency code in Java.
September 27, 2022
by George Ball
· 20,558 Views · 12 Likes
article thumbnail
Realtime React Coding in ClojureScript [Autumn 2022 Remix]
I love ClojureScript. The language, the look, the feeling when I type the code to make my React components with it, makes me stay up all night. It actually did yesterday when I try to pick up on a friend setup and get back a modern environment to do my coding. Let’s walk through the first few steps to get to a setup with a React counter in ClojureScript, all this with live code reloading from VSCode. Most Clojure people are veterans coders, and are mostly using emacs to get their job done. I am going to present a setup with VSCode and the minimal setup for coding at ease with it. Setup VSCode with Clava Clava requires clojure-lsp to be installed on your machine, and the installation process is described here. As a side note, to make things smooth, (and avoid this) I had to have npx installed globally: npm install -g npx --force Setup a new project with shadow-cljs Shadow CLJS User’s Guide will be at the core of this setup. I just picked it up yesterday thanks to my dear friend Tokoma, and I just love its speed, ease of use, and its full integration with the standard npm world. Supposing you have npx installed, if not let’s do it. npm install -g npx We will start by creating a new acme app, in the same fashion as the tutorial fromshadow-cljs: npx create-cljs-project acme-app I was a bit taken aback, this new generated app comes with the default setup, but: no build instruction no ClojureScript code whatsoever So you do have REPLs ready to run with: npx shadow-cljs node-repl # or npx shadow-cljs browser-repl But not much else. What we do have, is a set of files with the following structure (only keeping important files): . ├── package.json ├── package-lock.json ├── shadow-cljs.edn └── src ├── main └── test The file package.json from the standard nodejs world only contains a dev dependency to the Javascript part of ShadowCLJS: { "name": "bunny-app", "version": "0.0.1", "private": true, "devDependencies": { "shadow-cljs": "2.20.1" } } The second important file is the shadow-cljs.edn file, which is an EDN based the configuration used by shadow to do its magic, and at generation time its pretty bare: ;; shadow-cljs configuration {:source-paths ["src/dev" "src/main" "src/test"] :dependencies [] :builds {} So, first of all, we want to host an index.html file to do our javascript coding. We will: put it in public/index.html with some bare content, and we will add a reference to jsmain.js main.js is the file that will be generated from our ClojureScript code in a few seconds. Here is the source for HTML file. We need some ClojureScript code to get going, so in the file, srcmainacmefrontendapp.cljs: mkdir -p src/main/bunny/frontend touch src/main/bunny/frontend/app.cljs Let’s write some basic Clojure code: (ns bunny.frontend.app) (defn init [] (println "Hello Bunny")) We then update the :builds section of the shadow-cljs.edn file with: {:frontend {:target :browser :modules {:main {:init-fn acme.frontend.app/init} } There are multiple :target available: Supporting various targets :browser, :node-script, :npm-module, :react-native, :chrome-extension, ... We will use browser for now, and the to-be-compiled module’s function will be the init function in the ClojureScript file we just wrote above. We are ready, so let’s run the magic command: npx shadow-cljs watch frontend See that frontend is the build definition we wrote in shadow-cljs.edn, so make sure to use that in the watch command above. Ah … but we need something to host and make the files in the public folder available via a web server. Let’s go back to the shadow-cljs.edn file, and add: { ;... :dev-http {8080 "public"} ;... } Then we can head to: http://localhost:8080 And open the browser console to see our bunny showing up in the browser's console: It would be nice, if when saving the ClojureScript file, we could reload the code dynamically, and one way to do this is via annotations on functions. See how ^:devbefore-load/ and ^:devafter-load/ are being used. (defn init [] (println "Hello Bunny")) (defn ^:dev/before-load stop [] (js/console.log "stop")) (defn ^:dev/after-load start [] (js/console.log "start") (init)) Now saving the ClojureScript file, will automatically reload code triggered by the init function, and so we now have two rabbits in the console: Some raw DOM manipulation We will see later how to play with React, but for now, let’s see how we can simply add a rabbit picture in our HTML file. Basically, we would like to achieve the equivalent of the below JavaScript code: const img = document.createElement ("img"); img.src = "/bunny-512.webp"; document.body.appendChild (img); And providing, you have the bunny.webp picture in the public folder, the code below would work: (defn init [] (let [img (doto (.createElement js/document "img") (set! -src "/bunny-512.webp") (set! -height 64) (set! -width 64))] (.appendChild (.getElementById js/document "app") img))) It’s just a tad laborious to revert to using directly set! for setting properties on a dom element, so in a separate bunny.frontend.utils namespace, let’s create two convenient functions: (ns bunny.frontend.utils) (defn set-props [o property-map] (doseq [[k v] property-map] (.setAttribute o (name k) v))) (defn create-el [tag-name property-map] (let [el (.createElement js/document tag-name)] (set-props el property-map) el)) And let’s use that namespace from the main app namespace: (ns bunny.frontend.app (:require [acme.frontend.utils :as u])) (defn init [] (println “Init”) (let [img (u/create-el "img" {:src "/bunny-512.webp" :height 128 :width 128})] (.appendChild (.getElementById js/document "app") img))) And you should see a nice little rabbit. Of course, you can play with the :height and :width keys in the properties map, and see a new image bigger or smaller appearing in your browser. Going React These days, directly manipulating the DOM does feel a bit like cracking eggs with a hammer. Let’s see how we can use React, first without a ClojureScript wrapper, just the plain npm package. At the time of writing I had some glitches later on with React v18+Reagent, so let’s stick to version 17 for this article with: npm install [email protected] [email protected] The package.json file should now have those dependencies included: { "name": "bunny-app", "version": "0.0.1", "private": true, "devDependencies": { "shadow-cljs": "2.20.1" }, "dependencies": { "react": "^17.0.2", "react-dom": "^17.0.2" } } Those are not ClojureScript dependencies, so we do not have to update the :dependencies section of the shadow-cljs.edn file. (It stays the same). Now on to our ClojureScript code, note that we can have shortcuts when including the js dependencies straight in the :require section of the namespace. (ns bunny.frontend.app3 (:require ["react" :as react] ["react-dom" :as dom])) (defn init [] (dom/render (react/createElement "h2" nil (str "Hello, Bunny ")) (.getElementById js/document "app"))) The rest is pretty standard ClojureScript interop code, so we will leave the reader to scrutinise the three lines of code. The rendering works as expected, and you can check that adding more bunnies in our h2 component does the job and bunnies are multiplying like crazy. Adding a ClojureScript library I often find my self needing a time library somehow, just to be sure on timezone, and other leap years problems. Before moving on to using ClojureScript’s Reagent, let’s see how we can add it to our shadow-cljs project setup. The dependency cljs-time itself is defined as: [com.andrewmcveigh/cljs-time "0.5.2"] And we include it in the shadow-cljs.edn file as shown below: { ;... :dependencies [[com.andrewmcveigh/cljs-time "0.5.2"]] ;... } You’ll need to restart the watch command for this dependency to be actually picked up by the compiler. npx shadow-cljs watch frontend Then on to our updated React code with the cljs-time ClojureScript library, where we get the current date, to which we add one month and three weeks. (ns bunny.frontend.app4 (:require [cljs-time.core :as t :refer [plus months weeks]]) (:require ["react" :as react] ["react-dom" :as dom])) (defn init [] (dom/render (react/createElement "h2" nil (str "Hello, Bunny" (plus (t/now) (months 1) (weeks 3)))) (.getElementById js/document "app"))) And the equivalent rendered html in the browser: Does the job ! Easy coding with Reagent Reagent provides ClojureScripts like easy to use constructs around the React framework. As with did with the cljs-time library, we will first add the reagent library to the shadow-cljs.edn file, so with the changes from before that gives: { ;... :dependencies [[com.andrewmcveigh/cljs-time "0.5.2"][reagent "1.1.1"]] ;... } We will make a simple counter, the code is directly taken from cljs-counter updated to work with the latest reagent: (ns bunny.frontend.app5 (:require [reagent.core :as r][reagent.dom :as d])) (defonce state (r/atom {:model 0})) (defn increment [] (swap! state update :model inc)) (defn decrement [] (swap! state update :model dec)) (defn main [] [:div {:style “float:left;”} [:button {:on-click decrement} “-“] [:div (:model @state)] [:button {:on-click increment} “+”]]) (defn init [] (d/render [main] (.getElementById js/document “app”))) It does not look support sexy, but with just a bit of efforts, and more Reagentism we can do the below: (ns bunny.frontend.app5 (:require [clojure.string :as str]) (:require [reagent.core :as r][reagent.dom :as d])) (defonce state (r/atom {:model 0})) (defn increment [] (swap! state update :model inc)) (defn decrement [] (swap! state update :model dec)) (defn n-to-image[idx n] [:img {:key idx :src (str "/img/nums/" n ".png")}]) (defn counter[] (let [m (:model @state) m-as-characters (rest (str/split (str m) #""))] [:span (map-indexed n-to-image m-as-characters)])) (defn button [display fn] [:button {:style {:background-color "white"} :on-click fn} [:img {:src (str "/img/nums/" display "-key.png")}]] ) (defn main [] [:div (button "minus" decrement) (counter) (button "plus" increment)]) (defn init [] (d/render [main] (.getElementById js/document "app"))) And we icons downloaded from icon8 we now get something like the counter below: Advanced coding with Reagent The last example in this article shows how to (ns bunny.frontend.app6 (:require [reagent.core :as reagent] [reagent.dom :as dom])) (defonce app-state (reagent/atom {:seconds-elapsed 0})) (defn set-timeout! [ratom] (js/setTimeout #(swap! ratom update :seconds-elapsed inc) 1000)) (defn timer-render [ratom] (let [seconds-elapsed (:seconds-elapsed @ratom)] [:div "Seconds Elapsed: " seconds-elapsed])) (defn timer-component [ratom] (reagent/create-class {:reagent-render #(timer-render ratom) :component-did-mount #(set-timeout! ratom) :component-did-update #(set-timeout! ratom)})) (defn render! [] (dom/render [timer-component app-state] (.getElementById js/document "app"))) (defn init [] (render!)) And this gives the dynamically refreshing page below: We leave that to the reader to style this using the icon set from icon8 here again. Jack-in with Clava There’s just a little bit too much to know if we go in the details, so to finish this article we will just have a look at how to jack-in and code directly in the browser using Clava. To make sure we understand what is happening, let’s comment out the render! Call in the init function of our example with Reagent. (defn init [] (println "init") ;; (render!) ) Now let’s start a coding session via a browser REPL created from within VisualCode/Calva. If you have visual code and look at the bottom, you can see a greyed-out REPL icon, let’s click on it and open a new REPL session to the browser, using shadow-cljs. Or you can do this access the command “Start a project REPL”: Our whole setup is done via shadow-cljs so we will use that, but note that you have other REPL options: And we will select the build defined in the shadow-cljs.edn file: And the build kicks in ! At this stage, you have a ClojureScript REPL for the browser: but this REPL is not yet connected to the browser, so refresh the page in your browser. Let’s play with our newly created REPL and look at the effect in the browser . First, let’s execute a simple print statement from the REPL: And see that this actually translates immediately in the browser: Now, let’s try to render our reagent component as well. Notice, that we start in the wrong namespace so we will change that first, and for more impact we will update the internal timer contained in the app-state before rendering our reagent component. So at the REPL let’s write the commands below one by one: (ns bunny.frontend.app6) (swap! app-state update :seconds-elapsed #(+ % 100)) (render!) At the REPL at a glance that gives: And now we notice our browser started the reagent timer directly from 100. Voila. Summary In this article we briefly covered the basic for ClojureScript coding with VisualStudio Code, Shadow-cljs, Reagent, and Clava. We started by settings up the project, then moving on to pure coding from within ClojureScript. We then moved to perform interacting coding on Reagent components using Clava Jack-in facilities. Resources ClojureScript Cheatsheet Shadow-cljs user guide cljs-time infer-externs React Counter Further Readings Clojurescript Reagent Image-Previewing Selector | Tech.ToryAnderson.com Cropping images in ClojureScript. Displaying images in CSS is always a… | by Bingen Galartza Iparragirre | magnet.coop | Medium Wave Function Collapse Algorithm in ClojureScript · Andrey Listopadov Learn ClojureScript | Learn ClojureScript GitHub - tolitius/mount: managing Clojure and ClojureScript app state since (reset)
September 27, 2022
by Nicolas Modrzyk
· 4,497 Views · 1 Like
article thumbnail
Pagination With Spring Data Elasticsearch 4.4
Explanation of the pagination options within Spring Data Elasticsearch 4.4 using Elasticsearch 7 as a NoSQL database.
September 27, 2022
by Arnošt Havelka DZone Core CORE
· 13,510 Views · 1 Like
article thumbnail
Comparison and Usage of Javascript Engines in Camunda
In this article, let’s look at how to use Javascript as a scripting language in Camunda with the introduction of Java 15.
September 27, 2022
by Alok Singh
· 6,741 Views · 2 Likes
article thumbnail
What’s the Future of Device Management? 5 Predictions For What Lies Ahead
Managing devices is getting harder and harder. Here's how to prepare for the future.
September 27, 2022
by Mike McNeil
· 5,747 Views · 1 Like
  • Previous
  • ...
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • ...
  • Next
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook
×