How to execute method in class using Gradle task? - spring-boot

I want to execute Hello method in class using gradle task(at springboot). The sample is like below.
class MyClass
{
public void Hello()
{
System.out.println("Hello World");
}
}
Is there any way to execute Hello function in gradle task?
I had added below and tried but below task cannot parse MyClass token.
task myTest{
doLast {
println "Executing MyClass method"
def v = new MyClass();
v.Hello();
}
}

Related

Why is PropertyState Necessary

Suppose I'm developing a Gradle plugin and the inputs that some of the tasks the plugin configures depend on how it is configured via an extension. For example:
class MyTask extends DefaultTask {
#InputFile
File toTrack
#TaskAction
def run() {
println("The file now contains ${toTrack.text}")
}
}
class MyConfig {
File toTrack = new File('bad-default.txt')
}
class MyPlugin implements Plugin<Project> {
#Override
def apply(Project project) {
project.with {
extensions.create('config', MyConfig)
task('printChanges', type: MyTask) {
toTrack = config.toTrack
}
}
}
}
Unfortunately, this doesn't work correctly. The problem is that if I have a build.gradle like:
apply plugin: my-plugin
config {
toTrack = file('file-to-track.txt')
}
where I've specified a file to track, Gradle will evaluate the #InputFile on my task before the config block is run so it'll decide if the task is up to date or not by looking at bad-default.txt rather than file-to-track.txt.
The recommended fix to this seems to be to use PropertyState like so:
class MyTask extends DefaultTask {
PropertyState<File> toTrack = project.property(File)
#InputFile
File getToTrack { return toTrack.get() }
#TaskAction
def run() {
println("The file now contains ${toTrack.get().text}")
}
}
class MyConfig {
private PropertyState<File> toTrack
MyConfig(Project project) {
toTrack = = project.property(File)
toTrack.set('bad-default.txt')
}
void setToTrack(File fileToTrack) { toTrack.set(fileToTrack) }
}
class MyPlugin implements Plugin<Project> {
#Override
def apply(Project project) {
project.with {
extensions.create('config', MyConfig)
task('printChanges', type: MyTask) {
toTrack = config.toTrack
}
}
}
}
That works but it seems very verbose and the PropertyState stuff seems entirely unnecessary. It seems like the real fix was simply to change the #InputFile annotation to be on a getter instead of having it be on the property. In other words, I believe the following has the same effect and is less code and easier to understand:
class MyTask extends DefaultTask {
File toTrack
// This is the only change: put the annotation on a getter
#InputFile
File getToTrack() { return toTrack }
#TaskAction
def run() {
println("The file now contains ${toTrack.text}")
}
}
class MyConfig {
File toTrack = new File('bad-default.txt')
}
class MyPlugin implements Plugin<Project> {
#Override
def apply(Project project) {
project.with {
extensions.create('config', MyConfig)
task('printChanges', type: MyTask) {
toTrack = config.toTrack
}
}
}
}
With some experiments this does seem to have the desired effect. What am I missing? Is there ever a time when PropertyState is necessary?
The problem is not the time #InputFile is evaluated. #InputFile is evaluated just before the task is executed, so after the configuration phase has finished and during gradles execution phase. The problem PropertyState is solving is the wiring between an extension and a task.
let's look again on your apply method:
def apply(Project project) {
project.with {
extensions.create('config', MyConfig)
task('printChanges', type: MyTask) {
toTrack = config.toTrack
}
}
}
here you:
1) Create your custom extension with the default value provided in the MyConfig class.
2) Link the value currently set in MyConfig to the MyTask toTrack property.
Now looking at the plugin usage:
apply plugin: my-plugin
config {
toTrack = file('file-to-track.txt')
}
here you:
1) Apply the plugin (and basically executing the apply method of your plugin).
2) Reconfigure the MyConfig#toTrack extension property.
But what isn't happening here, is updating the value in the printChanges task. That's what PropertyState is solving. It has nothing todo with Task inputs and outputs evaluation.

How to implement this 'dynamic block' in Gradle?

I am new to gradle. So let straight to the point. I want to implement the block as below. Note that the libraries is dynamic, and available for other developers to add on for the needed libraries.
libraries {
slf4j 'org.slf4j:slf4j-api:1.7.21'
junit 'junit:junit:4.12'
}
So that I can call them out like this.
dependencies {
compile libraries.slf4j
testCompile libraries.junit
}
I am not sure how to make it. But I found some related solution from here. As shown below:
apply plugin: GreetingPlugin
greeting {
message 'Hi'
greeter 'Gradle'
}
class GreetingPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create("greeting", GreetingPluginExtension)
project.task('hello') {
doLast {
println "${project.greeting.message} from ${project.greeting.greeter}"
}
}
}
}
class GreetingPluginExtension {
String message
String greeter
}
The problem is as I add on to the greeting block, I need to declare them in GreetingPluginExtension as well. Any idea how to make it such that only update on greeting block?
What you need to do is to utilize groovy meta programming. Below you can find just a sample, however fully functional.
apply plugin: LibrariesPlugin
libraries {
slf4j 'org.slf4j:slf4j-api:1.7.21'
junit 'junit:junit:4.12'
}
class LibrariesPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create("libraries", LibrariesPluginExtension)
project.task('printLib') {
doLast {
println "$project.libraries.slf4j"
println "$project.libraries.junit"
project.libraries.each {
println "$it.key -> $it.value"
}
}
}
}
}
class LibrariesPluginExtension {
Map libraries = [:]
def methodMissing(String name, args) {
// TODO you need to do some arg checking here
libraries[name] = args[0]
}
def propertyMissing(String name) {
// TODO same here
libraries[name]
}
Iterator iterator() {
libraries.iterator()
}
}

Can a groovy build script class acces the Gradle project directly?

Can a groovy class (located in buildSrc/src/main/groovy) access the project directly, or does the project have to be passed in explicitly?
I am able to access the project by explicitly passing it in as a method parameter, but I do not want to have to pass it in. For an example, I would like to be able to get access to the project via a static method call. Is this type of implicit access possible?
Explicit Access
import org.gradle.api.Project
class MyClazz {
static void foo(Project project) {
println project.version
}
}
Task in build.gradle
task foo() << {
MyClazz.foo(project)
}
Implicit Access via Static Method Call (this is the desired access pattern)
import org.gradle.api.Project
class MyClazz {
static void foo() {
println Project.getProject().version
}
}
Task in build.gradle
task foo() << {
MyClazz.foo()
}
You can use Groovy extension methods to do this.
here's a self-contained example, but should work with Gradle too:
class Project {
// we add this method dynamically
//static getProject() { [ version: 2.3 ] }
}
class MyClazz {
static void foo() {
println Project.getProject().version
}
}
class Gradle {
static def main(args) {
Project.metaClass.static.getProject = { [ version: 4.2 ] }
MyClazz.foo()
}
}

Using AOP in Grails is not working for service

I use Grails 2.2.3 and type following codes in grails-app/conf/spring/resources.groovy
beans = {
xmlns aop:"http://www.springframework.org/schema/aop"
loggerAspect(com.test.aop.aspect.LoggerAspect)
aop{
config("proxy-target-class": true) {
aspect(id: "beforeService", ref: "loggerAspect") {
before method: "beforeMethod",
pointcut: "execution(* com.test.DemoService.serviceMethod())"
}
aspect(id: "afterService", ref: "loggerAspect") {
after method: "afterMethod",
pointcut: "execution(* com.test.DemoService.serviceMethod())"
}
}
}
}
then, create an aspect class under src/groovy/com/test/aop/aspect
package com.test.aop.aspect
class LoggerAspect {
def beforeMethod(JoinPoint jp){
println '-- Before Method.'
}
def afterMethod(JoinPoint jp){
println '-- After Method.'
}
}
And create a service class under grails-app/services/com/test
package com.test
class DemoService {
def serviceMethod() {
println 'In DemoService.serviceMethod()'
}
}
And create a controller to call service for testing
package com.test
class DemoController {
def index() {
println 'In DemoController.index()'
def demoService = new DemoService()
demoService.serviceMethod()
render 'Hello World'
}
}
Finally, I test the aop through url:
http://myhost:8080/grails-spring-aop/demo/index
and the aop is not invoked. Following is the result:
| Server running. Browse to http://myhost:8080/grails-spring-aop/
In DemoController.index()
In DemoService.serviceMethod()
I add the following line to the service class:
static transactional = false
And, it's still not working for me.
Anyone an idea how this can be solved or is this not possible.
Or I do the something wrong.
Thanks.
You need to inject the service (spring bean) in the controller instead of creating an instance of it.
package com.test
class DemoController {
def demoService //Autowired, not required to specify in resources.groovy
def index() {
println 'In DemoController.index()'
demoService.serviceMethod()
render 'Hello World'
}
}
Moreover, the aspect can be made annotation based as below:
package com.test.aop.aspect
#Aspect
class LoggerAspect {
//A more generic advice would be as below
//#Before("execution(* com.test.*.*(..))")
#Before("com.test.DemoService.serviceMethod()")
def beforeMethod(){
println '-- Before Method.'
}
//A more generic advice would be as below
//#Around("execution(* com.test.*.*(..))")
#After("com.test.DemoService.serviceMethod()")
def afterMethod(){
println '-- After Method.'
}
}
And resources.groovy could become:
beans = {
loggerAspect(com.test.aop.aspect.LoggerAspect)
xmlns aop:"http://www.springframework.org/schema/aop"
aop{
config("proxy-target-class": true) {
aspect(id: "loggerAspectService", ref: "loggerAspect")
}
}
}

Override plugin convention property with project property

I am trying to understand how to set a plugin convention property from a project property.
Here is the customPluginWithConvention example from the gradle distribution (gradle-0.9.2\samples\userguide\organizeBuildLogic\customPluginWithConvention\build.gradle)
apply plugin: GreetingPlugin
greeting = 'Hi from Gradle'
class GreetingPlugin implements Plugin<Project> {
def void apply(Project project) {
project.convention.plugins.greet = new GreetingPluginConvention()
project.task('hello') << {
println project.convention.plugins.greet.greeting
}
}
}
class GreetingPluginConvention {
def String greeting = 'Hello from GreetingPlugin'
}
Running this script with no project property:
>gradle hello
:hello
Hi from Gradle
BUILD SUCCESSFUL
And now trying to set a custom message via setting a project property:
>gradle -Pgreeting=goodbye hello
:hello
Hello from GreetingPlugin
Instead of the expected "goodbye" the default greeting of the convention is shown. Is it possible to override the message?
Is it possible to override the message?
Not yet, but we should try to make it possible. Please create an issue at http://jira.codehaus.org/browse/GRADLE.

Resources