10 Things You Can Do With Groovy Closures!

Поделиться
HTML-код
  • Опубликовано: 20 янв 2025

Комментарии • 82

  • @szymonstepniak
    @szymonstepniak  4 года назад +18

    What do you think about this type of video? Should we do another survey like that in the future? :)

    • @mrozi5838
      @mrozi5838 4 года назад +6

      Maybe next time something about testing applications written in groovy?

    • @camilongii
      @camilongii 4 года назад +1

      The video was amazing, also I would like to see some things like Spock tricks.

    • @uszebr
      @uszebr 4 года назад +1

      yep, I also using Groovy for testing. Some tips for using it with DB and maybe with API's

    • @KidJV
      @KidJV 3 года назад +1

      new to groovy, big help not only to groovy I'm not familiar with some of these concepts especially delegation, currying, composition and etc. Thanks!

    • @szymonstepniak
      @szymonstepniak  3 года назад

      @@KidJV Happy to hear that! Have a good day! :)

  • @KotlinBack
    @KotlinBack 3 года назад +3

    As a Java developer I have spent a lot of time trying to understand groovy's closers in order to learn Gradle. Thx you a lot for this and groovy DSL tutorials. It helped me so much!!

    • @szymonstepniak
      @szymonstepniak  3 года назад

      Thanks for your kind words, Evgenij! Take care, and have a good day!

  • @vdiachuk5191
    @vdiachuk5191 2 года назад +1

    best groovy lessons I have ever seen

    • @szymonstepniak
      @szymonstepniak  2 года назад

      Thank you so much for your kind words! Take care, and have a good day!

  • @damirmurat7433
    @damirmurat7433 4 года назад +6

    Great content, impressive production. Brilliant.

  • @brianjohnsen3992
    @brianjohnsen3992 4 года назад +5

    Great work, Szymon!
    I didn't know the "closure >> closure" syntax, brilliant :-D
    The video quality is amazing!

    • @szymonstepniak
      @szymonstepniak  4 года назад

      Thanks, Brian! 😀 I'm happy to hear you found this video useful! 👍

  • @SiddharthaGhoshSid
    @SiddharthaGhoshSid 4 года назад +3

    This is so fabulous, cleared a lot of my own doubts. Thanks for the video!

    • @szymonstepniak
      @szymonstepniak  3 года назад +2

      Thanks for your kind words! It proves this video was worth creating. Have a good day!

  • @marknellemann
    @marknellemann 4 года назад +1

    Another great video - thanks. I always learn something new. Keep up the good work.

    • @szymonstepniak
      @szymonstepniak  4 года назад

      Thank you, Mark! That's the best thing I could hear today! 🙏

  • @mattdlr847
    @mattdlr847 2 года назад +1

    Great work. Thank you

  • @PrashantJoshi-v2c
    @PrashantJoshi-v2c 11 месяцев назад

    Great job Szymon!
    Thank you so much.

  • @enriconolastname3471
    @enriconolastname3471 Год назад

    Thank you! Very clear tutorial🫶

  • @uszebr
    @uszebr 4 года назад +1

    really helpful Groovy tips!

    • @szymonstepniak
      @szymonstepniak  4 года назад

      Thanks, Viktor! I'm glad to hear you find it useful. Have a good day! 👍

  • @fazlizekiqi2324
    @fazlizekiqi2324 3 года назад +1

    Great video. Keep up the good work.

    • @szymonstepniak
      @szymonstepniak  3 года назад

      Thank you so much for your kind words, Fazli! Take care and have a good day!

  • @Hitz9092
    @Hitz9092 2 года назад +1

    Really Helpful

    • @szymonstepniak
      @szymonstepniak  2 года назад

      Glad to hear that! Take care, and have a good day!

  • @michalbotor
    @michalbotor 3 года назад +1

    finally! someone showed me how to do an elegant histogram of data in groovy
    ```
    def hist = [:].withDefault({ 0 })
    def data = [3, 2, 2, 1, 1, 2, 4, 1, 3, 1]
    data.each { hist[it] += 1 }
    println("data: $data")
    println("hist: $hist")
    ```
    output
    ```
    data: [3, 2, 2, 1, 1, 2, 4, 1, 3, 1]
    hist: [3:2, 2:3, 1:4, 4:1]
    ```
    thank you. 😀

    • @szymonstepniak
      @szymonstepniak  3 года назад

      There is even a shorter way to build your expected output:
      data.countBy { it }
      I'm gonna record a video about interesting collection methods in Groovy soon. Thanks for helping me in crafting this idea. Have a good day!

  • @kishnakhadayat9261
    @kishnakhadayat9261 3 года назад +1

    very helpfull..make more vedios about gsp, mysql connection groovy applications

  • @BestHKisDLM
    @BestHKisDLM 4 года назад +1

    Great content. Thank you.

  • @acemanftw
    @acemanftw 4 года назад +2

    Amazing video! Liked and subbed :)

    • @szymonstepniak
      @szymonstepniak  4 года назад +1

      Thanks a lot for the kind words! I hope you find my other Groovy related videos useful as well :-) Have a good day!

  • @NielsBaltodano
    @NielsBaltodano 2 года назад +1

    Gracias por compartir el conocimiento

  • @anversadhat760
    @anversadhat760 3 года назад +2

    8:23 The spaceship operator () delegates to the compareTo method
    assert (1 1) == 0
    assert (1 2) == -1
    assert (2 1) == 1
    assert ('a' 'z') == -1

    • @szymonstepniak
      @szymonstepniak  3 года назад

      Thanks for sharing these examples! Have a good day!

  • @themastermindisyash
    @themastermindisyash 4 года назад +1

    Hello @Szymon Stepniak, how can we pass specific elements to the closure say for example we want to pass 20 elements at a time from the map and pass it to the closure. We want to have sleep/wait after every 20 elements passed. The map has around 1000 elements.

    • @szymonstepniak
      @szymonstepniak  4 года назад +1

      Hi, Yash! Thanks for the comment! Could you share some code snippet or something, so I can better understand what you are trying to achieve? Are you trying to chunk a map (or a list), iterate it, and call some closure with arguments? Explaining your use case with an example would be most efficient to understand your problem better. I will do my best to help you.

    • @themastermindisyash
      @themastermindisyash 4 года назад

      @@szymonstepniak following is the line of code:
      Script {
      def appnamelist = params.APP_NAME.tokenize(',')
      def parts = [:]
      appnamelist.each { name ->
      parts[name] = {
      stage(){}
      stage() {}
      stage() {}
      }
      }
      }
      parallel parts
      }
      In the parts[name] I am getting 1000 elements I want to control the flow of elements such that only 50 elements are passed to parts[name]
      Could you let me know what can be done for it.

    • @szymonstepniak
      @szymonstepniak  4 года назад +1

      @@themastermindisyash I don't know what exactly do you expect from this pipeline part, but it looks broken to me. If you put multiple stages inside the single parallel stage, Blue Ocean UI won't be even able to render them correctly and you will end up seeing only the first (out of three) stage from each part[name] parallel stage.
      I tried to recreate your example with chunked input (using Groovy's Collection.collate(num) method that chunks a list to a list of lists of size num) to slice an input list of 100 elements into a list of lists of size 10, so I can create the "parts" map ten times with 10 elements only (a closure with 3 stages that just echo the name of the app), and then I can run "parallel parts" so it triggers 10 parallel stages (that contain 3 sequential stages), and it killed my Jenkins. I run this experiment only to show you that this is not the right way to utilize parallel stages in the Jenkins pipeline. Here is the code I run on my Jenkins, I also attached the screenshot of Blue Ocean UI that couldn't render those sequential stages in each parallel stage:
      gist.github.com/wololock/acce19567af677a535337a7408d2e6ac
      I would suggest taking a step back and rethinking what you are trying to achieve. This input of 1,000 app names sounds suspicious and it suggests that you are trying to utilize a single Jenkinsfile to build 1,000 apps in parallel, where every parallel stage triggers three sequential stages. This is wrong, this is going to kill your Jenkins server.

    • @themastermindisyash
      @themastermindisyash 4 года назад

      @@szymonstepniak Then which other approach can we adapt inorder to achieve the objective. I have to provision 1000 application with same set of stages for each one. Can you suggest a better approach here which can help achieve the objective?

    • @szymonstepniak
      @szymonstepniak  4 года назад +1

      @@themastermindisyash Well, the truth is I don't know what your objective is. I can only guess based on your question, which does not provide much information. I don't know what provisioning application means, and why you can't do it in the dedicated Jenkinsfiles. However, what I'm guessing is you want to parallel common steps and you want to split huge input between those parallel steps. The only thing that comes to my mind is something like this:
      gist.github.com/wololock/3aeb2bdb48bf4ee1f57aada58ee8f6d0
      It requires setting two Jenkins pipelines job. The first one (called Jenkinsfile-A.groovy in the attached gist) takes the input (1,000 app names) and it chunks this input to the desired size (I used chunk size 20 in the attached example). Then it iterates those chunks and for each chunk, it triggers the second pipeline job (named "parallel-job-name", you need to use a real pipeline job name instead) with the parameter APP_NAME and a value that represents only this chunk. It will trigger the job with the next chunk only when the previous job is done (you can change it by setting "wait" to false.) The second Jenkins pipeline (called Jenkinsfile-B.groovy in the attached gist) takes the chunked input and it runs those 3 stages (or any number of stages) and it parallelizes each stage for every value taken from the APP_NAME parameter. As you can see, it uses a "parallel" step in every stage, and this is on purpose - this way you can get a clean view in the Blue Ocean UI.
      This is what I deducted from your question, and I don't know if this is something you are trying to achieve. Jenkins pipeline works most efficiently when it does its job in the context of a single application/project. Your task (provision 1,000 application, whatever it means) sounds like not the best fit for the single Jenkins pipeline job, and thus you may have to apply some workarounds.

  • @blaugranisto
    @blaugranisto 3 года назад +1

    Great content! What is the IDE/script editor you are using?

    • @szymonstepniak
      @szymonstepniak  3 года назад +2

      Thanks for your kind words, Omar! I use IntelliJ IDEA in this video (and in my daily work.) You can download IDEA Community Edition for free with a support for Groovy language. Hope it helps. Take care and have a good day!

  • @ntarunmenon1
    @ntarunmenon1 4 года назад +1

    Thanks for the amazing content.

  • @HighOctaneNews570
    @HighOctaneNews570 Год назад +1

    Thank you

  • @SebastianPlagge
    @SebastianPlagge 4 года назад +2

    Really helpful video. I am still working on Jenkins pipelines and I am still a total noob with Groovy. I guess I can refactor a lot of code, to make it easier to read.
    By the way, do you also use IntelliJ for when you work on a Jenkins file? If yes, do use IntelliJ out of the box or do you use some plugin or something like that?
    Fancy intro :D

    • @szymonstepniak
      @szymonstepniak  4 года назад

      Hi, Sebastian! I use plain IntelliJ IDEA with no additional plugins for the Jenkinsfile support. There is a way to get some code autocompletion in the Jenkinsfile using the GDSL file. This blog post explains how to set it up - st-g.de/2016/08/jenkins-pipeline-autocompletion-in-intellij

    • @SebastianPlagge
      @SebastianPlagge 4 года назад +1

      @@szymonstepniak I used GDSL last year, when I had my first steps with Jenkins, but I was not completely happy with it. Maybe I should give it a try again.
      How much Groovy do you use in your Jenkinsfile. Just very simple stuff or even more adanced stuff.
      We have a pretty complex Maven Dependcy situation and depending on the branch, our artifacts needs to get the correct version from a different pom.xml.
      So in release/x we need pom.xml from another release/x (I mean nexus), same for feature, develop.
      Anyways, in the end, depending on what is going on (build from branch release/x, feature/x, develop or pull request from a to b) I need to get a slightly different version from Nexus. It works fine but with a lot of "ifs" and when conditions for different stages, it is a lot of code and maybe not the most simple way.
      Sorry for the confusing text. My question is, do you face similar problems and if yes, do you prefer to have more sepperat stages or how do you handle complex stuff.
      Hopefully you can understand, what I am talking about :D

    • @szymonstepniak
      @szymonstepniak  4 года назад

      @@SebastianPlagge I can't think of any example like that in any of the pipelines I worked with, but this is because I always advocate for the simplest pipeline workflow possible. For instance, in the company I currently work for, we treat every artifact as production-ready, so it doesn't matter what branch you build it from, it always has to pass the same set of stages. What I could suggest to you, however, is to look at Maven Profiles, and maybe try to orchestrate your situation with the profiles. Then you could just define a map of profiles, where you map a profile name to a list of branch patterns (including regex) that should use specific maven profile, e.g.
      def profiles = [
      prod: ["master", /release\/.*/],
      dev: ["develop", /PR-.*/]
      ]
      And then you could extract profile name with something like this - gist.github.com/wololock/94e1ca3579486fdc6468f1fc9646a8b4
      I don't know if it answers your specific problem, but maybe it will help you to improve your current workflow.

    • @SebastianPlagge
      @SebastianPlagge 4 года назад +1

      @@szymonstepniak Maven profiles are a pretty good idea. Unfortunately the projects are pretty old and there are maaany projects :(.
      Probably we will start to develop new stuff (this or next year), there I can put my ideas into it. The stuff we currently work on started many years before I entered the company.
      There are a lot of workarounds, many different coding styles and so on.
      The stages are pretty similar, the tricky part is to get the correct maven parent pom.
      The stuff worked fine with hudson and svn because the team did not care about "branches" and so on. They basically had one branch, which is develop :D. I am the one who introduced that stuff, because I want to push CI/CD.
      I will take a look at maven profiles for sure. Thanks for the example on GitHub!

    • @szymonstepniak
      @szymonstepniak  4 года назад

      Sounds good, good luck, Sebastian! 👍

  • @themastermindisyash
    @themastermindisyash 4 года назад +1

    How to iterate two lists of strings in a closure such that two list will have similar elements wherein some elements are prefix with a letter in one list? Is there are way to use nested closure?

    • @szymonstepniak
      @szymonstepniak  4 года назад +1

      Hi Yash! Could you elaborate on your question please? Are you trying to iterate the first list, and then for each element iterate another list and use this element as a prefix to construct a new string?
      list1.collect { a -> list2.collect { b -> "${a}_${b}" } }.flatten()
      Or is it something else you are trying to achieve? Let me know and I will do my best to help you. Have a good day!

    • @themastermindisyash
      @themastermindisyash 4 года назад +1

      @@szymonstepniak hi Szymon, I have one list of elements and now a new list needs to be added which has mostly same elements but few elements in the same list will be prefixed with alphabet b. The goal is to iterate through both the list at the same time where first element of one list and second Element of list two should be considered and then simultaneously the others. 1:1
      I wanted to pass those elements tot he jenkins job. I am iterating through one list but now need to add second list in the same logic.
      Thank you
      Regards,
      Yash

    • @szymonstepniak
      @szymonstepniak  4 года назад +1

      @@themastermindisyash Can you share some code you have written so far and could you point to the place where you are confused? Also, sharing an expected result on an exemplary input will help me understand better what you are trying to achieve.

    • @themastermindisyash
      @themastermindisyash 4 года назад

      Hi Szymon, Greetings!
      We have two lists
      A = [abc, 1cdf, df123, 2bfc, dfyu, ghre, 6gyh]
      B = [abc, b1cdf, df123, b2bfc, dfyu, ghre, b6gyh ]
      These are the two lists. I want to pass the values of both the lists 1:1 (first element of first list with first element of second list)
      I want to pass these elements to stages parallelly
      Regards,
      Yash

    • @szymonstepniak
      @szymonstepniak  4 года назад +1

      @@themastermindisyash What does the "pass these elements to stages parallelly" mean specifically? I don't know what you mean by that.
      Regarding constructing a list of pairs that represent values at the same index of two lists, you can use the transpose() method. You can call it on a list that stores two (or more) lists as its elements. Assuming that A and B are the lists from your example, here is an exemplary code:
      def C = [A,B].transpose()
      It creates a new list C that looks like this:
      [[abc, abc], [1cdf, b1cdf], [df123, df123], [2bfc, b2bfc], [dfyu, dfyu], [ghre, ghre], [6gyh, b6gyh]]
      Now, you can use it in an iteration and do something while iterating such a list. For instance, if you want to print what both values in a stored pair are, you can do something like this:
      [A,B].transpose().each { a,b -> println "a = ${a}, b = ${b}" }
      (As you can see, it assigns first value to the a variable, and the second one to the b variable inside the each closure.) It will print something like this:
      a = abc, b = abc
      a = 1cdf, b = b1cdf
      a = df123, b = df123
      a = 2bfc, b = b2bfc
      a = dfyu, b = dfyu
      a = ghre, b = ghre
      a = 6gyh, b = b6gyh
      This example simply prints the value of both elements, but you can use it as a starting point to achieve what you expect. Hope it helps.

  • @manonthedollar
    @manonthedollar 4 года назад +1

    Thank you, I have always found the purpose of a closure a bit confusing! Am I correct to say it's sort of like a lambda function?

    • @szymonstepniak
      @szymonstepniak  4 года назад

      Yes, I would say your intuition is accurate. From the formal perspective, a lambda function is an anonymous function that may use only the defined parameters (e.g. f x = x + 2). A closure, however, allows to use variables/symbols that are defined outside the expression (e.g. f x = x + y + 2), but it requires that all used variables/symbols are defined in the surrounding environment. That way a closure become a context-dependent, because this exemplary "y" variable may store a different value depending on the context. (Which I shown by using myName variable with different values in the video.) But Groovy closure breaks this formal definition by allowing using symbols/variables that are not defined in the surrounding context, and this allows Groovy closures to use e.g. delegation mechanism. Just like in the example I shown in the video - we can define a closure that uses `add(1)` method, and this method is not known in the environment the closure is defined in. It becomes clear what `add(1)` means when we explicitly set the delegate to the list object. So the Groovy closure depends on the surrounding context (`myName` variable in the example), as well as it depends on the delegation mechanism (using `add(1)` plus `closure.delegate = list`). I hope it helps and does not confuse you even more :-)

    • @manonthedollar
      @manonthedollar 4 года назад +1

      @@szymonstepniak It helps a ton! Thank you so much for sharing your knowledge.

  • @lakshminarasimmanv
    @lakshminarasimmanv 2 года назад +1

    Nice video, but please remove the background music, its really very distracting.

    • @szymonstepniak
      @szymonstepniak  2 года назад

      Thanks for your kind words and suggestion, Lakshmi! Take care, and have a good day!

  • @shivakumarreddy1865
    @shivakumarreddy1865 3 года назад

    Any groovy developer DM me I have a problem in coding my project is total in groovy technology I am new to groovy

  • @Daveooooooooooo0
    @Daveooooooooooo0 3 месяца назад

    שמעון

  • @dovdembin
    @dovdembin Год назад +1

    which groovy are you using I got errors
    "Caught: groovy.lang.MissingMethodException: No signature of method: java.util.regex.Matcher.replaceAll() is applicable for argument types: (Main$_run_closure1) values: [Main$_run_closure1@64d2d351]
    Possible solutions: replaceAll(java.lang.String)
    "

    • @szymonstepniak
      @szymonstepniak  Год назад +1

      I think it was Groovy 3 at the time of recording this video.