How to add common dependencies using Gradle custom Plugin - java

I am trying to write one custom Gradle plugin and intent is we have good number of microservice.
Those microservices use lots of common library. So instead of declaring those library in each sub-project.
I want to create one custom Gradle plugin where I will add all library and other project just need to use that plugin.
I am done with custom plugin and its integration with other project and looks fine.
But not sure how to add common dependencies in plugin. either implementing Plugin interface or something else.
In my plugin class I am trying to the following things and its not working.
Can someone suggest me how can achieve this task. is it something I need to change here or need to follow some different approach.
public class CommonResourcesPlugin implements Plugin<Project> {
#Override
public void apply(Project project) {
log.info("Applying depdencies ");
project.getDependencies().add("implementation", "org.springframework.boot:spring-boot-starter-web");
project.getDependencies().add("implementation", "org.springframework.boot:spring-boot-starter-actuator");
}
}

Related

Extending xtext new project wizard

I'm using xtext 2.13/java8 to create a DSL with IDE as described in "Implementing Domain-Specific Languages with Xtext and XTend 2nd edition".
The IDE includes a new project wizard, and the DSL includes a code generator that produces java code. The generated java code depends on some helper classes in another support plugin that is provided as part of the DSL project.
I can export the update site and install into a fresh eclipse.
There, I can create a new DSL project that compiles the DSL file into java.
I would like to extend the new project wizard so that I can automatically add the dependency on my support plugin to the generated MANIFEST file in the new project. I can add it manually after the project is created (the plugin is present in the installed feature), but I don't want users to have to do that.
org.eclipse.xtext.ui.wizard.AbstractPluginProjectCreator has code that adds the dependencies on logging packages, but I don't see any way to extend or override that logic using any extension points. Is there a way to do this?
This turned out to be not too hard, though it took a half-day of experimenting to find it.
The xtext project defines a generated MyDSLProjectCreator class in the *.ui plugin under src-gen in the .ui.wizard package that defines the method we need to override:
#Override
protected List<String> getRequiredBundles() {
return Lists.newArrayList(DSL_PROJECT_NAME);
}
By default, this adds just the DSL project bundle to the dependencies of the new project. I need to add also the support plugins. I can't edit this generated file, but I can extend it, so I defined MyExtendedProjectCreator class in the src folder of the same .ui.wizard package that extends this class (java source):
public class MyExtendedProjectCreator extends MyDslProjectCreator {
#Override
protected List<String> getRequiredBundles() {
return Lists.newArrayList(DSL_PROJECT_NAME,
"my.plugin.id");
}
}
To invoke that project creator instead of the default, I had to override another method in the MyDslUiModule class. This can be found in the .ui package under src (xtend file):
#FinalFieldsConstructor
class MyDslUiModule extends AbstractMyDslUiModule {
public def override Class<? extends IProjectCreator> bindIProjectCreator() {
MyExtendedProjectCreator;
}
}

Developing application with plugin support in Java

I have been researching on how to develop an application that can load plugins.
So far, I've seen that this can be done by defining an Interface, and have the plugins implement it.
However, my current issue is on how to load the plugins when they're packed in Jars. Is there a "best" way to do it?
The current logic I'm thinking of is to get each plugin and inside their Jar look for the class that implements the Interface. But I don't know how to do such lookup. I think that this logic may not be a good one, but I couldn't find any useful information on this specific topic.
**Edit1: **
Adding more information:
The intended plugins would be Jar files contained inside a subdirectory where the main application's Jar would be located, like this:
Application's folder
|- Main_Application.jar
|- Plugins
|- Plugin1.jar
|- Plugin2.jar
|- Steve's_plugin.jar
And so on.
What I expect is that the Application will be able to load all plugins inside the folder at runtime. So in the code, it would only be aware that the plugin's folder should exist and there should be Jars inside such folder.
Let's say I have a plugin interface like this:
interface Plugin
{
public void run();
}
Plugins would be identified by a class that implements such interface, like so
class Plugin1 implements Plugin
{
//attributes and other methods
#override
public void run()
{
//something happens here
}
}
class Plugin2 implements Plugin
{
//attributes and other methods
#override
public void run()
{
//something happens here
}
}
The Application should be compiled only once, and be able to load any Plugins added to the folder when it is executed.
For the Application to be able to load any Plugin, do I need to establish rules on the contents of the Jar, like package name and the class that implements the interface? Or it is expected that the class implementing the plugin interface could be in any package within the Jar, and have any name?
This is the more generic approach to what I would like to do with such plugins. In short, I'm planning to build an Application that will have tabs, and each plugin will provide the Interface and Functionality of each tab. I'm trying this because I want to be able to maintain each tab separately, and don't want to recompile the whole application because of changes in only one component that don't affect the others at all.
Get the list of plugin jars:
File[] jars = new File("Plugins").listFiles();
Then, use the code from this answer about loading all classes from a JAR file, but run it once for each file in jars whose name ends in ".jar". At the bottom of the loop body, after
Class c = cl.loadClass(className);
continue with
if (Plugin.class.isAssignableFrom(c)) {
Plugin plugin = (Plugin) c.newInstance();
// And then, do something with the plugin here
}
I share #Mifeet's concerns about security - you might want to use a SecurityManager to limit what the plugin code is allowed to do.
Very old question, but still relevant if some one searches.. Adding to the accepted answer,
Use OSGI framework
Refer Apache Felix for a reference implementation
If you wanted to have a light version of OSGi, try to use apache connect - pojosr

gradle: best way to encapsulate custom dsl

my screencast, i hope my aExtFunc can work in build.gradle in any projects, but intellij idea raise
Cannot resolve symbol 'gradleExt'
my question is: how to fix it.
Defining dependency on the project
dependencies{
compile project(':gradleExt')
}
Doesn't mean that you can work with the content of the project in your build script:
task ATask() {
new gradleExt.Ext().aExtFunc()
}
You probably need to create new groovy class directly in the build.gradle file implementing desired behaviour. Or if you really want to have the implementation in different place you need to add the classpath dependecy into the buildScript{} block. See the documentation on implementing custom tasks:
http://www.gradle.org/docs/current/userguide/custom_tasks.html
If you want custom dsl, then custom gradle plugin is probably what you are looking for
http://www.gradle.org/docs/current/userguide/custom_plugins.html
And also please double check the documentation on multi-project builds if that might be of any use to you, it is not clear from the "my screencast" what your overall gradle setup is. I would post the link, but I don't have enough reputation.

How to allow user to change the version of the library which is used by a plugin in Gradle?

In my plugin I call static bootstrapping method MutationCoverageReport.main(arg) from a library which is a compile dependency of my plugin. I would like to allow a plugin user to change the version of the library which should be used (assuming the selected version has compatible API).
I could advice user to exclude a transitive dependency from my plugin and add a dependency to the library in the requested version manually to buildscript.dependencies.classpath in his build.gradle, but this is not very elegant:
buildscript {
(...)
dependencies {
classpath('info.solidsoft.gradle.pitest:gradle-pitest-plugin:0.32.0') {
exclude(group: 'org.pitest')
}
classpath 'org.pitest:pitest-command-line:0.33'
}
}
I would like to be able to use libVersion parameter in my configuration closure, but I have some problems with two solutions I tried.
1. I could need to remove transitive dependencies from my plugin (an original library version and its dependencies) and add a library in requested version (from configuration closure) as a buildscript dependency.
In afterEvaluate it is to late (configurations are resolved) and I had problem to successfully hook with beforeEvaluate (is it triggered for single module project?).
2. I could change a classpath which is used to execute a static method from a library.
To do that I could create a custom class loader which would use my library classes (in requested version) before delegating to the parent class loader. I also would have to replace one liner with MutationCoverageReport.main(arg) with the reflection call using the new class loader.
Maybe there is a simpler way to modify a classpath by a plugin with which the mentioned method will be called?
Main questions. What would be the best way to allow plugin users to define the version of the library the plugin executes?
I'm not sure this is what you're looking for, but here's how the Jacoco plugin allows the user to configure the library being used.
JacocoPluginExtension
class JacocoPluginExtension {
// ...
String toolVersion = '0.32.0'
// ...
}
JacocoPlugin
class JacocoPlugin implements Plugin<Project> {
// ...
config.dependencies.add(this.project.dependencies.create("org.jacoco:org.jacoco.ant:${extension.toolVersion}"))
// ...
}
In another question about executing Java class with a separate classpath Peter Niederwieser provided 3 approaches. In the end modify my task to extend JavaExec. I set explicit set execution classpath which is separate from plugin execution classpath and can contain different library version.
The drawback is allows only to run main method, but it wasn't a problem in my case.

What is the correct way of extending the Gradle Java Plugin?

I have a custom type of archive that I want to build with gradle, the structure is equals to a standard java project so I'd like to use it but then I have other resources that go to a custom location, additionally I'd like to package the archive as a zip and not as a jar, I'm thinking of creating a subclass of the Java gradle plugin but I'm not sure if this is the way to go. What would be the appropriate way of creating this new plugin that inherits the Java functionality?
if you want to create a custom java plugin that has conventions, that differ from the standard gradle plugin, I recommend to start with the java-base plugin. The java-base plugin does provide the functionality of sourcesets but does not already any of them.
Instead of inheriting a plugin you should apply it in your custom plugin:
class YourCustomJavaPlugin implements Plugin<Project> {
void apply(Project project){
// 1st apply the 'java-base' plugin
project.apply(plugin:'java-base')
// 2nd apply your own conventions on top
project.sourceSets.create("customSourceSet")
Zip myZip = project.tasks.create("zip", Zip)
...
}
}
cheers,
René

Categories

Resources