Corda - why is deployNodes outputting a useless JAR? - corda

I'm performing this on Windows, so some of these operations might be different for Linux/Mac users.
Steps To Reproduce
Step 1: Clone the Corda V3 Kotlin template into a new folder
git clone https://github.com/corda/cordapp-template-kotlin.git MyFirstCorDapp
Step 2: clean and deploy nodes with gradle
./gradlew clean dN
Output
This image illustrates the JAR files that have been built and deployed into a cordapp folder for a node
Questions
Why does deployNodes produce MyFirstCorDapp-0.1.jar? This file
doesn't seem necessary.
Why is cordapp-contracts-states-0.1.jar so big? Given that this
was compiled directly from the kotlin template with no changes, I'd
expect this to be much smaller.

The reason why MyFirstCordapp-0.1.jar is appearing is because of this line:
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
The root project has a kotlin plugin so creates a jar so the deployNodes deploys it.
One solution would be to use a subprojects closure to skip the root project
task deployNodes(type: net.corda.plugins.Cordform) {
subprojects.each { subproject ->
dependsOn(
subproject.tasks.matching { task ->
(task.name == 'jar')
}
)
}
The reason why cordapp-contracts-states-0.1.jar is "so big" (775 KB) is because the corda gradle plugin packs some dependencies in it.

Related

How to prepare the nodes folder structure for the network-bootstrapper?

I am trying to create a bootstrap test network on aws, and I am using this -
java -jar corda-tools-network-bootstrapper-4.5.jar --dir ./
I get -
Bootstrapping local test network in /home/ubuntu No nodes found
The jar seems to be correct. The docs state - https://docs.corda.net/docs/corda-os/4.5/network-bootstrapper.html -
java -jar network-bootstrapper-4.5.jar --dir <nodes-root-dir>
I cannot find network-bootstrapper-4.5.jar but only the corda-tools-network-bootstrapper-4.5.jar. The error seems to be something related to the node.conf file.
Has anyone any ideas?
If you follow the steps that are mentioned here, you will see that it says:
Create a directory containing a node config file...for each node
The keywords are node config file; so you must do the following:
Build your nodes: From the root folder of your project run ./gradlew deployNodes; this will create a folder for every node that you defined inside the deployNodes Gradle task of your root build.gradle file.
The folders will be inside path-to-project-folder/build/nodes. If you inspect the folders, you'll see that each node has a node.conf file which the documentation of the bootstrapper is talking about.
Run the bootstrapper command where the <nodes-root-dir> is path-to-project-folder/build/nodes since it contains all of your nodes.

Specify jar structure in sbt assembly

When sbt-assembly builds a fat jar, it places all the dependencies in the main folder. I need to construct a jar that looks like this
--domain
domain classes
-- lib
dependency classes
is it possible to do this with sbt assembly, or any other plugin?
If you want to seperate your app jar file and your dependecy jar files, here is the most practical method i found with sbt;
Create project/plugins.sbt file if not exists and add following line:
addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.8.0")
After adding this line refresh your project.
Note: Plugin version might change in time.
When sbt refresh finishes update your build.sbt file like this:
lazy val MyApp = project.in(file("."))
.settings(artifactName := {(
sv: ScalaVersion,
module: ModuleID,
artifact: Artifact) => "MyApp.jar"
})
.settings(packSettings)
Then run:
sbt pack
Or if you're doing this for child project, run this:
sbt "project childproject" clean pack
This will nicely seperate your main jar file and your dependency jars.
Your app jar will be in target scala folder.
Your dependencies will be in target/pack/lib.
In this way you can deploy your dependencies once.
And whenever you change your app, you can just deploy your app jar file.
So in every change you don't have to deploy an uber jar file.
Also in production, you can run your app like:
java -cp "MyApp.jar:dependency_jars_folder/*" com.myapp.App

Gradle project dependency does not reference SNAPSHOT jar

I am trying to create a fat jar file in a multi-project Gradle build, something like the following:
root
+-- project1
+-- project2
project1 provides the basic functionality, which is then used by project2 to create an executable jar. The executable JAR needs to contain all of the code from the dependencies so that it can be run standalone.
For external dependencies this works fine. In project2 I create a new configuration:
apply plugin: 'maven'
apply plugin: 'java'
configurations {
// configuration for JARs that need to be included in the final packaging
includeInJar
}
and then add the dependencies:
dependencies {
includeInJar 'com.fasterxml.jackson.core:jackson-databind:2.2.3'
...
configurations.compile.extendsFrom(configurations.includeInJar)
}
The packaging then looks like this:
jar {
manifest {
attributes "Main-Class": "com.acme.project1.MyTest"
}
// import all dependencies into the Jar so that it can be run easily
from {
configurations.includeInJar.collect {
it.isDirectory() ? it : zipTree(it)
}
}
}
The jar is correctly built with all of the files from the external dependencies. The problem comes with the project dependency to project1:
includeInJar project(':project1')
When this is present, I get an error when it tries to assemble the JAR that it can't find the jar (e.g. project1-0.4.0.jar) in the project1 build/libs directory as it does not exist. The message is correct, as project1 builds a SNAPSHOT jar (e.g. project1-0.4.0-SNAPSHOT.jar).
The question is, why does the configuration refer to the non-SNAPSHOT jar when the project is building SNAPSHOT jars? What can I change so that it finds the correct jar?
As a comment :
In my opinion, fatjar is not a great pattern. Maybe Gradle application plugin would fit your need ?
I found the answer to my own question.
The problem was that we have some additional scripting at the project level which is apparantly making a change to the version at the end of the configuration phase.
When the fat jar configuration is assembled, the 'plain' version is used. This is then changed to the -SNAPSHOT version before the jars are built.
Moving the from { ... } code into the build phase by wrapping it in doFirst { ... } is enough to fix the problem, although the real fix is obviously to avoid changing the version in the middle of the in the first place.

pubxml web publish tool Event Lifecycle

I am using the Web publishing tool from Visual Studio 2012 to publish to File System. I learned that I can open my *.pubxml in the Properties folder to do more advanced things.
What I want to do is run a command line application at the end of the publishing task.
I would usually do it in a Custom Target and execute it after one of the build in Events like this.
<Target Name="CustomAfterPublish" AfterTargets="GatherAllFilesToPublish">
</Target>
The problem is that GatherAllFilesToPublish is way to early because I want to execute it at the very last, after publishing was done.
Is there a list or does someone know the build in events and there order in which they are fired? Basically the Event Lifecycle of a FileSystem web publish.
Or how can I fire a Target manually at the very end?
I tried following without success:
<Target Name="Msg" AfterTargets="PipelineDeployPhase;MSDeployPublish;Package">
And also every each of them individually.
So what's the very last hook of the publishing lifecycle?
---> Edited
I added already tracing. The problem is that the files were copied to a temp path and after that all files are deleted. So copying to the destination will not work after "GatherAllFilesToPublish"See my trace from the command line window here...
1>------ Build started: Project: Dependency of a project: Release Any CPU ------
2>------ Build started: Project: Dependency of another project, Configuration: Release Any CPU ------
3>------ Build started: Project: Web, Configuration: Release Any CPU ------
4>------ Publish started: Project: Web, Configuration: Release Any CPU ------
4>Transformed Web.config using C:\...\Web.Release.config into obj\Release\TransformWebConfig\transformed\Web.config.
4>Copying all files to temporary location below for package/publish:
4>obj\Release\Package\PackageTmp.
**<------------- Here is the place where my excutable is called ---------------------------------**
4>Deleting existing files...
4>Publishing folder /...
4>Publishing folder App_Browsers...
4>Publishing folder App_Themes...
4>Publishing folder bin...
4>Site was published successfully file:///C:/Test
4>
========== Build: 3 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========
========== Publish: 1 succeeded, 0 failed, 0 skipped ==========
Thanks for any help.
As far as I can tell GatherAllFilesToPublish is the last event available. However, depending on your requirements you may still be able to use this event.
Instead of performing operations on files in the final publish location, you can target the intermediate files written to the location below (where ProjectDir is the folder of your project obviously)
/ProjectDir/obj/Release/Package/PackageTmp/
It seems that Visual Studio does a straight copy of all files in this directory. So, when hooking into GatherAllFilesToPublish you should be able to make any changes to the files in this directory and they will be reflected in the final publish location.
Related Information
If you'd like to verify that GatherAllFilesToPublish is truly the last event you can do this yourself by enabling Diagnostic build output.
Tools -> Options -> Projects and Solutions -> Build and Run -> MSBuild
project build output verbosity -> Diagnostic
Build the project and search for Done building target "GatherAllFilesToPublish", for me this was the last trigger before it started copying the files to the publish location.
I had the same problem. Your solution
Coping first to the temp directory and let web publish picking up the
coping for publishing
was helpful.
I just want to share for other people how it can be done:
<Target Name="CopyConfigForPublish" AfterTargets="CopyAllFilesToSingleFolderForPackage" Condition="exists('$(SolutionDir)Web.Common\bin\$(Configuration)\Log.config')">
<Copy SourceFiles="$(SolutionDir)Web.Common\bin\$(Configuration)\Log.config" DestinationFolder="$(WPPAllFilesInSingleFolder)" />
</Target>
I had a similar issue.
As far as i could check, "GatherAllFilesToPublish" is the last target you can deal with. You can use it doing an AfterTargets.
And use this >
$(MSBuildProjectDirectory)\obj\Release\Package\PackageTmp
To manipulate anything there.
What I did was creating an .bat file to do the dirty work.
You can find out which one is the variable that stores the relative part of the path (\obj\Release\Package\PackageTmp) and use it on more refined way.

How to use Gradle to download JAR dependencies on production site?

In the hope of finding the solution on Google as it seems a very general task, I've been trying to do this past few weeks but strangely I couldn't find anything!
What I'm doing:
I am writing an small application, It will be at most a 20KB JAR file in the end. However it has many dependencies, Hibernate and SLF4J to name a few. Directly including these dependencies with the jar file will make it 9Mb.
What is used:
Gradle is used as the build tool. the custom task fatJar creates the jar including all required dependency jar files from (the original) maven repository.
The problem
with my slow internet connection I'd rather not to directly include dependencies, but download these them on the server and not my local production site. What would be the Gradle task like to:
Read the dependencies from jar file
Download them (I know how to do it during Gradle build task).
Add them to class path
Add classpath defined in MANIFEST.mf too
run the jar, by main class defined in MANIFEST.mf
I've read gradle documentation over and over, but no help.

Resources