If you're willing to use Spring you can create Clojure-based Spring Beans 
[1] and let Spring inject (autowire) them into your Java-based 
Spring-Beans. And if you like you could use Spring just as a factory that 
you invoke. I would still define interfaces (that you want to use from 
Java) in Java, so that IDE autocompletion, generics etc. work as excepted. 
HTH
Henrik

[1] https://github.com/henrik42/spring-break

Example:

<bean id="load_script_code" 
        class="clojure.lang.Compiler" 
        factory-method="loadFile">
        <constructor-arg 
value="src/main/clojure/no-namespace-scripts/script-code.clj" />
</bean>

Am Montag, 10. Juni 2019 17:34:25 UTC+2 schrieb eglue:
>
> > I find the glue code is actually small in practice (I've done a couple 
> of real systems this way). This particular example is a little weird 
> because it's just making a domain object, but generally you're writing the 
> glue to provide a factory method for a facade. Below the facade, the 
> Clojure code can make new objects just fine, so you're staying in Clojure 
> for the rest of it.
>
> Very helpful, thanks!
>
> On Monday, June 10, 2019 at 8:20:44 AM UTC-5, Alex Miller wrote:
>>
>>
>> On Mon, Jun 10, 2019 at 12:04 AM eglue <atd...@gmail.com> wrote:
>>
>>> This is great, Alex, thanks. (Sorry, I deleted from underneath you and 
>>> reposted to fix the title before I saw your reply...)
>>>
>>> The latter option, writing interfaces and classes in Java and calling w/ 
>>> the glue code is a great option.
>>>
>>> However one big motivator for people moving from Java to langs like 
>>> Scala and Kotlin is being able to implement those bean/record types, eg, 
>>> with such little fanfare & boilerplate (eg in Clojure, using defrecord is 
>>> so concise). 
>>>
>>
>> The problem with wanting the Clojure-y version from Java is that those 
>> interfaces are generic and weird from the Java side. So either you get 
>> bean-like code familiar to Java users or generic collection/keyword 
>> interfaces that will be weird to use from Java. I heard your goal as "be 
>> friendly from Java", which means, making bean-like interfaces. On the 
>> Clojure side, it's pretty easy to macro-ize the creation of those over 
>> defrecords or whatever, so it could still be  a lot less macro work, just 
>> depends how far you want to go with it. You don't get all the benefits of 
>> Clojure from Java; you have to be in Clojure for the many related design 
>> decisions to compound together. There's no magic solution to that (other 
>> than "just use Clojure" :).
>>  
>>
>>> And you can sometimes end up with a handful of these, so the 'glue code' 
>>> isn't quite so small. Also gen-class and definterface I find similarly 
>>> nice. 
>>>
>>
>> I find the glue code is actually small in practice (I've done a couple of 
>> real systems this way). This particular example is a little weird because 
>> it's just making a domain object, but generally you're writing the glue to 
>> provide a factory method for a facade. Below the facade, the Clojure code 
>> can make new objects just fine, so you're staying in Clojure for the rest 
>> of it.
>>  
>>
>>> I wonder if there's a path to improve what you're calling option #2. 
>>> Specifically the needing to AOT compile *everything*. It seems I should 
>>> only have to AOT/precompile the surface area that my Java consumer wants to 
>>> link with. At runtime perhaps there'd be some creative way to leave out the 
>>> AOT classes (which would just have been used for static-time compiling) and 
>>> when the JVM tries to load those classes some agent could interject and do 
>>> the dynamic Clojure loading?
>>>
>>
>> Seems like you're taking the hardest path and trying to make it harder. I 
>> just don't see the point in running at this one, sorry. My experience is 
>> that the approach above works great and has none of these issues.
>>  
>>
>>>
>>>
>>> On Sunday, June 9, 2019 at 11:21:28 PM UTC-5, Alex Miller wrote:
>>>>
>>>> Looks like the title for this is backwards if I understand the intent, 
>>>> should be calling Clojure from Java, right?
>>>>
>>>> Java code is going to invoke methods on classes (that's all it knows 
>>>> how to do). You have several options:
>>>>
>>>> 1) Use the Clojure Java API to invoke the Clojure runtime - here you're 
>>>> leveraging the Clojure runtime's Java impl core to call into Clojure 
>>>> (Stu's 
>>>> example)
>>>> 2) Use protocols, records, and/or genclass to actually produce Java 
>>>> classes (your example, I think). 
>>>> 3) Define your interface as a set of Java interfaces. Implement this 
>>>> interface in Clojure. You will need a small amount of glue code to provide 
>>>> the API impl (some kind of a factory to give you the impl of the Java 
>>>> interface - either written in Java or using #1). 
>>>>
>>>> #1 is straightforward but tedious - it's really only worthwhile if you 
>>>> have a small amount of this code and hide the use of it.
>>>> #2 has significant downsides - needing to compile everything, all 
>>>> methods are just going to take/return Java Objects, no javadoc on apis,  
>>>> etc. 
>>>> #3 has advantages in all those areas. You write your Java interface 
>>>> where you can best write it ... in Java (with Javadoc, and Java 
>>>> interfaces, 
>>>> and all the niceties Java users want). IDEs can autocomplete on the Java 
>>>> interfaces. You don't have to AOT - factories can reify or load protocol 
>>>> instances as needed as they return objects. You can even reload internal 
>>>> vars with a connected REPL without restarting the app.
>>>>
>>>> The last does take a bit of planning to set up - you need API code (in 
>>>> Java), and Clojure code that relies on that Java code. lein makes it 
>>>> pretty 
>>>> trivial to put those in one project and compile in that order.
>>>>
>>>> I pushed an example up here:
>>>>
>>>> https://github.com/puredanger/clojure-from-java
>>>>
>>>> It defines a Java interface (java/cfj/Event.java 
>>>> <https://github.com/puredanger/clojure-from-java/blob/master/java/cfj/Event.java>),
>>>>  
>>>> a static helper to hook the Clojure (java/cfj/Support.java 
>>>> <https://github.com/puredanger/clojure-from-java/blob/master/java/cfj/Support.java>),
>>>>  
>>>> which uses the Clojure Java API to load the Clojure instance in 
>>>> clj/core/cfj.clj 
>>>> <https://github.com/puredanger/clojure-from-java/blob/master/src/cfj/core.clj>.
>>>>  
>>>> Just `lein uberjar` and you're done. Use the Support API from Java as any 
>>>> other Java class. No AOT required.
>>>>
>>>>
>>>>
>>>> On Sunday, June 9, 2019 at 9:53:56 PM UTC-5, eglue wrote:
>>>>>
>>>>> I've been stalking Clojure for a while but now doing it professionally 
>>>>> full-time (woo hoo!).
>>>>>
>>>>> I saw a Stuart Halloway tweet responding to someone who'd found it a 
>>>>> "soul-crushing, miserable experience."
>>>>>
>>>>> I had a similar miserable experience and figured it was just me, but 
>>>>> am now suspecting that's not the case. (Happy to be shown the light 
>>>>> however.)
>>>>>
>>>>> Stuart H posted https://github.com/stuarthalloway/clojure-from-java 
>>>>> <https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Fstuarthalloway%2Fclojure-from-java&sa=D&sntz=1&usg=AFQjCNFxHASS9MQ07WZ5St1GE9g1WckHFg>
>>>>>  to 
>>>>> demonstrate the ease of Java consuming Clojure, but I find it far more 
>>>>> important to be able to *compile* Java against Clojure interfaces not 
>>>>> invoke it dynamically from Java....because dynamic invocation from Java 
>>>>> is 
>>>>> unwieldy to the point of it being a likely deal breaker for any Java 
>>>>> shop. 
>>>>> Dynamically loading classes and invoking methods.... c'mon, no one's 
>>>>> going 
>>>>> to ask their Java devs to do this.
>>>>>
>>>>> If Clojure doesn't have a good compile-time consumption story for Java 
>>>>> consumers, I think that's a loss. (Even if it is just providing better 
>>>>> docs 
>>>>> or archetype/bootstrap examples in this regard.) Because otherwise Java 
>>>>> code bases around the world could be eaten away by (compiled) Clojure 
>>>>> from 
>>>>> the inside out, giving Java dev teams enough time to be overtaken by the 
>>>>> miracle that is Clojure.
>>>>>
>>>>> Inspired by Stuart's example, I was successful in putting together a 
>>>>> quick build to achieve this ideal: 
>>>>> https://github.com/atdixon/clojure-from-java 
>>>>> <https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Fatdixon%2Fclojure-from-java&sa=D&sntz=1&usg=AFQjCNG0DEccFtsm0Norw4jQ_qw-dezdZw>
>>>>>
>>>>> However, I have a few open questions:
>>>>>
>>>>> - when I tried to AOT only the public-facing clojure code that I 
>>>>> needed to compile against, I found out at runtime that this wasn't going 
>>>>> to 
>>>>> work. Dynamic clojure code was loading my same types into 
>>>>> DynamicClassLoader and when my statically-compiled, root-class-loaded 
>>>>> code 
>>>>> was getting executed the ClassCastExceptions of course were flying. So am 
>>>>> I 
>>>>> right to think that you have to AOT everything in order to do this right?
>>>>> - IDE support (for me, Cursive) "works" but is non-ideal; you have to 
>>>>> manually compile the dependee/Clojure jar, then Cursive will let you 
>>>>> execute Java code against the manually aot-compiled Clojure code 
>>>>> - AOT producing generics/generic types doens't seem to be part of any 
>>>>> of this... is this a lacuna in the Clojure AOT space, are there libs that 
>>>>> can help here?
>>>>>
>>>>> This story ^^, if made easier, seems to me would boost Clojure 
>>>>> adoption in Java/JVM shops.
>>>>>
>>>>> What am I missing?
>>>>>
>>>>>
>>>>> -- 
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to clo...@googlegroups.com
>>> Note that posts from new members are moderated - please be patient with 
>>> your first post.
>>> To unsubscribe from this group, send email to
>>> clo...@googlegroups.com
>>> For more options, visit this group at
>>> http://groups.google.com/group/clojure?hl=en
>>> --- 
>>> You received this message because you are subscribed to a topic in the 
>>> Google Groups "Clojure" group.
>>> To unsubscribe from this topic, visit 
>>> https://groups.google.com/d/topic/clojure/aejqMwraPk8/unsubscribe.
>>> To unsubscribe from this group and all its topics, send an email to 
>>> clo...@googlegroups.com.
>>> To view this discussion on the web visit 
>>> https://groups.google.com/d/msgid/clojure/07753636-3414-481f-8836-763ca85675ce%40googlegroups.com
>>>  
>>> <https://groups.google.com/d/msgid/clojure/07753636-3414-481f-8836-763ca85675ce%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/clojure/e373728d-b243-4195-b8ec-92a1b7549c0d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to