I've developed a Multi Agent System application with the Jason agent platform which also uses the Jade agent framework for its infrastructure. The project works fine with Eclipse. However, I want to create a jar file of the project but since it's not a Java application, it does not have a main class. At Jason's FAQ Web Page, they've given three options for "How to run my application without JasonIDE" with the third option being the one for creating the jar file:
cd <the directory of you application>
ant -f bin/build.xml jar
java -jar <your application>.jar
I've gone through the first two steps and the jar file is created successfully. But when I try to run the jar file as stated at the third step, I get the message "Storing configuration C:\Users\Ali.jason\user.properties" at the console and the "Jason Configuration" window pops up.
I've read a lot about creating jar files, but they are all for Java applications with main classes. The closer I got for a Jason application (the only one) was here at another StackOverflow question which has a problem about the second step of the same code. I've updated my build.xml file according to it, to contain the "Main-Class" info, with the difference being:
<manifest>
<attribute name="Main-Class" value="jason.infra.jade.RunJadeMAS"/>
</manifest>
which is my case with the Jade infrastructure, instead of the centralised infrastructure there:
<manifest>
<attribute name="Main-Class" value="jason.infra.centralised.RunCentralisedMAS"/>
</manifest>
This time, the jar file is created successfully again, but when I try to run it, I got the following message at the console:
Exception in thread "main" java.lang.NoClassDefFoundError: jade/core/ProfileImpl
.......
Caused by: java.lang.ClassNotFoundException: jade.core.ProfileImpl
"jade.core.ProfileImpl" is not stated at the build.xml file explicitly and I already have the jade library at the build.xml file:
<pathelement location="C:\Users\Ali\Desktop\Project\jade\lib\jade.jar"/>
"jade.jar" is also already in the system path and classpath. I've searched for this problem, but could not find anything. Do you have any suggestions?
Related
We have an Asp.Net Core 2.0 web service, which we deploy in a Docker container.
For the web service we generate an xml documentation file and we use that file in Swagger-ui.
This works well for the xml documentation generated from the project itsself, but I can't get the xml comments that are generated for an included package visible when the web service is deployed in a Docker container.
The nuget package (also created by us) does contain an xml documentation file and we can make swagger use it when running the service on a local machine.
The documentation is made available to swagger by calling .IncludeXmlComments and the path to the documentation is determined by getting the path to the assembly and then replacing the .dll extension with .xml.
I suspect that the xml doc file of the package is not included in the container and can therefore not be found. In the Dockerfile I see the command
COPY publish .
I would either like a command that also adds/copies the package's xml doc file, or know how to make the xml doc file part of the publish assets.
Any other solution that makes this work in a robust way (not just on my machine) is welcome too.
EDIT:
we now have the extra xml doc file in the Docker container, but Swagger still doesn't show the descriptions that are provided in that file (which it does when running locally).
We used something similar to this:
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
<ItemGroup>
<DocFile Include="$(USERPROFILE)\.nuget\packages\{packagename}\**\lib\$(TargetFramework)\{PackageName}.xml" />
</ItemGroup>
<Copy SourceFiles="#(DocFile)" DestinationFolder="$(PublishDir)" SkipUnchangedFiles="false" />
</Target>
In which {PackageName} should be replaced by the actual name of your package. The wild card in the path keeps it version independent (although we must check if this now causes issues, as we have multiple versions).
Make sure you had checked XML Documentation checkbox for Release configuration under Project properties-> Build-> XML Documentation File. You might have already checked it for Debug configuration but not for Release Configuration. Select Release from dropdown under project properties and check XML Documentation file checkbox. Your docker RUN dotnet publish "" -c Release -o /app wouldn't produce Documentation XML file unless you check the checkbox for Release configuration.
I'll answer my own question, as a co-worker found out how to solve this.
You only need to change the nuget package, just follow these steps:
Create a "build" folder in your project
In that folder create a file with extension .targets (say projectname.targets) with content
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)projectname.xml">
<Link>projectname.xml</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
Edit the csproj file, add this before the final </Project> tag
<ItemGroup>
<None Include="bin\$(Configuration)\$(TargetFramework)\projectname.xml" Pack="true" PackagePath="build" />
<None Include="build\projectname.targets" Pack="true" PackagePath="build" />
</ItemGroup>
<ItemGroup>
<Folder Include="build\" />
<Folder Include="Properties\" />
</ItemGroup>
Substitute "projectname with your name of choice, we used the name of our project.
These modifications will add the xml documentation file of the package in the root of (the) project(s) that use it with properties Build Action: None and Copy to Output Directory: Copy always.
After that we could see the xml comments from the package also if it was deployed in a Docker container, no modifications to the Docker file were necessary.
Generally, we will not expose API documentation in a production environment. The documentation is useful for the dev environment.
Hence i figured out a different work around for this.
I have run the build & publish commands with default configuration i.e., debug.
RUN dotnet build -o /app
RUN dotnet publish -o /app
I have deployed this in my dev environment for UI developer reference.
I hope this helps.
I used a very basic build file taken from the sample configure-was-derby.xml:
<property name="worklight.server.install.dir" value="C:/Worklight70"/>
<property name="config.migration.tool.enable" value="true"/>
<target name="minimal-update">
<updateapplicationserver id="" contextroot="/AreaClienti">
<project warfile="C:/temp/AreaClienti.war"/>
<applicationserver>
<websphereapplicationserver installdir="C:/WebSphere85/AppServer"/" profile="AppSrv01" user="wasuser" password="xxxxx">
<server name="server1"/>
</websphereapplicationserver>
</applicationserver>
</updateapplicationserver>
</target>
Recently I was able to reproduce the issue on my laptop installation and I believe I found the cause: please review the following analysis and confirm the results.
I originally installed the war file manually from WAS admin console, and when I run the Ant minimal-update with the above build file it failed with the mentioned error
The MobileFirst Project WAR file is not currently deployed in the WAS
profile at ...
Then I removed the manually installed war file and reinstalled it using Ant install target.
At this point the minimal-update run successfully.
I found out that the Ant installation created into WAS config structure
profile_root/config/cells/cell_name/nodes/node_name/servers/server1
a new Worklight directory containing the worklight-jee-library.jar file and a derby subdir with the derby driver jar.
Apparently the minimal-update Ant task makes a preliminary check on the existence of the Worklight directory and it fails if it's missing.
Can you please confirm that this is true ?
Of course the Worklight directory is not created by the standard WAS installation process.
So, after a console installation of the runtime war the Ant minimal-update always fails!
If I manually add the Worklight dir in WAS config, then the Ant minimal-update starts running just fine.
IMHO, altering in such way the standard WAS config structure is not very clean.
Said that, is it a valid workaround in case we initially install the runtime war with standard WAS admin procedures ?
Furthemore, also the returned error message could have been a bit more clear: please let me know if there is any debug option to make the Ant tasks more verbose.
At last, let me ask one further question.
I noticed that the Ant execution writes log files in the directory
user_root/.mobilefirst_platform_server
Is there any way to redirect those logs into a different dir to avoid the risk of filling up the user root ?
Apparently the minimal-update Ant task makes a preliminary check on the existence of the Worklight directory and it fails if it's missing. Can you please confirm that this is true ?
That's correct.
Is there any way to redirect those logs into a different dir to avoid the risk of filling up the user root ?
Unfortunately not.
I am using Ant to build my project and deploy it to JBoss. Ant is building using jboss-home/server/default/lib jars. But during deployment it gives error:
java.lang.Error: Unresolved compilation problems:
The import org.apache.commons.lang3 cannot be resolved
StringUtils cannot be resolved
I am using commons-lang3-3.1.jar for StringUtils class by following Ant entry:
<path id="classpath">
<fileset dir="${lib.dir}" includes="**/*.jar">
<include name="{jboss.home}/server/default/lib/commons-lang3-3.1.jar" />
Well, for me it seems like compilation error, but still I can suggest a few things.
Try to include 'missing' library into your aplication (for example, place it into web-inf/lib if it is war packaging or use descriptor - application.xml or jboss-app.xml) and see what will happen.
Check if your jboss is actually using the lib: the fact, that jar is located inside jboss directory, does not mean that it will be actually loaded. I don't know what version of jboss you are using, but for jboss as7 it is possible to disable any jar from modules via module.xml or via specific server configuration file (like, standalone.xml).
I could not find a proper answer to the following question : while creating an executable jar from groovy compiled sources, I cannot simply include groovy-all-version.jar in a lib directory (as I would do in java) but I need to extract all the classes from the jar and package them with my own classes as otherwise I get an exception. This actually is the case with all libraries I may want to use.
Not clear ? Let's see an example.
toto.groovy belonging to package titi is compiled in a build directory which looks like this :
build
lib
groovy-all-1.8.4.jar
titi
toto.class
and a MANIFEST.MF that will be included in the jar contains the lines:
Main-Class: titi.toto
Class-Path: lib/groovy-all-1.8.4.jar
Executable jar creation is done with the following ant target in build.xml:
<jar destfile="${build.exe.dir}/${exe.name}"
basedir="${build.dir}"
manifest="${src.conf.dir}/MANIFEST.MF"
/>
Now if I try to execute the jar, I get
$ java -jar target/toto.jar
Exception in thread "main" java.lang.NoClassDefFoundError: groovy/lang/Script
(I've checked that the groovy.lang.Script class exists.)
On the other hand, if I unjar groovy-all-version.jar in build by adding an unjar task before the jar, execution goes fine. OK, it works, but it slows down the compilation process and I'd like to understand...
Any feedback is highly appreciated.
I want to use the FTP task in ant, and I have found the appropriate jar files and got everything working fine. I have put the jar files in a "libs" directory alongside the other files used in the build. The only problem is that the user must run "ant -lib commons-net-ftp-2.0.jar" to make a build; I would really prefer that it were possible to just run "ant" with no arguments.
Reading the ant optional tasks intallation page, I see that there are five ways one can load up extra libraries in ant, and none of them are really what I'm looking for. I do not want to force the user to make any modifications to their system to run this task; it should be possible to just load it from the "libs" directory inside of our product's source folder. So that means setting the global CLASSPATH is also out (which is a bad idea anyways).
The last option, as noted in the documentation, is the preferred approach... loading the jarfiles individually from the build script itself. I have done this in the past with the ant-contrib tasks and JUnit, and would like to do that here, but I don't see how I can accomplish this. The FTP task doesn't support a nested classpath element, and I don't know the XML resource I would need to load this library via a taskdef. How can I load the libraries from within ant?
Edit: In response to the answers and questions which have been posted here so far, I'm using ant 1.7.1. Making an ftp taskdef definitely does not work; that throws the following error:
BUILD FAILED
/my/path/build.xml:13: taskdef class org.apache.tools.ant.taskdefs.optional.net.FTP cannot be found
Perhaps this is because the classname is wrong. How exactly do I find the classname I'm supposed to use if I only have a jarfile? It's not documented anywhere, and I couldn't find anything in the jar itself resembling that path.
The problem you are having is due to the different class-loaders in use. The Commons Net classes must be loaded by the same class-loader that loads the FTP task. Because the FTP task is loaded by Ant on start-up, you need to add the Commons Net to Ant's classpath so that it is loaded by the same class-loader. That's why the documentation gives you 4 different ways to do this.
I agree that none of them are ideal (the CLASSPATH environment variable being the worst). One way around this is to supply a shell script with your project that invokes Ant and passes the apporpriate -lib argument. You then get people to use this rather than invoking Ant directly. In fact, you could deviously name it 'ant' so that it gets run instead of the existing 'ant' on the path (this only works if the current directory is on the path, ahead of other directories).
The fifth option in the documentation is great in theory. They finally fixed the class-loading problems in 1.7.0. Unfortunately, as you mention, nobody retro-fitted the FTP task to take a classpath. You could try submitting an enhancement request, but this won't help in the short term.
There is one other option, which isn't any better than the others. Instead of making sure that the Commons Net classes are loaded by the class-loader that loads the FTP task, you could make sure that the FTP task is loaded by the class-loader that loads the Commons Net classes. To do this you have to remove the ant-commons-lib.jar file from the 'lib' directory of the Ant installation. This means that the FTP task won't get loaded on start-up. This is actually why the optional tasks are broken up into so many separate JARs - so that they can be individually removed. Put this JAR file alongside the Commons Net JAR file so that it can be loaded at the same time. Then you can do something like this (I tried this and it works):
<taskdef name="ftp"
classname="org.apache.tools.ant.taskdefs.optional.net.FTP">
<classpath>
<pathelement location="${basedir}/lib/ant-commons-net.jar"/>
<pathelement location="${basedir}/lib/commons-net-2.0.jar"/>
</classpath>
</taskdef>
<ftp server="yourserver.com"
userid="anonymous"
password="blah">
<fileset dir="somedirectory"/>
</ftp>
But this is probably a worse option than just using the -lib switch (with or without a wrapper script). The only other thing I can think of is to try to find a third-party FTP task to use instead of the default one.
I have a solution:
you can download a new "classloader" task from http://enitsys.sourceforge.net/ant-classloadertask/ and load it whith:
<taskdef resource="net/jtools/classloadertask/antlib.xml"
classpath="XXX/ant-classloadertask.jar"/>
Naw can do things like loading classes with the same classloader that ant use for his task:
<classloader loader="system" classpath="XXX/commons-net-2.0.jar"/>
or "loader="project""
Then you definde your task:
<taskdef name="ftp" classname="org.apache.tools.ant.taskdefs.optional.net.FTP"/>
and go :-)
So I succeeded in doing this for the ant-salesforce.jar that you get when trying to do salesforce work (fun...)
Check to see if the jar has an xml file in it that looks something like this:
<antlib>
<typedef name="compileAndTest" classname="com.salesforce.ant.CompileAndTest"/>
....
</antlib>
Then in ant give it a taskdev that reads that file from inside the given jar, like this:
<taskdef resource="com/salesforce/antlib.xml" classpath="lib/ant-salesforce.jar" />
Hope that helps some.
Ah, man, this is just so nasty. I run ant from eclipse. I don't want to reconfigure ant in eclipse for new workspaces, so here's what I decided to do, to decouple running the task and configuring ant. I extracted the ftp task to a separate build file. Next I added a native call to the command line to start a completely new ant process with the required libraries on the path:
<target name="deploy-ftp">
<exec command="ant">
<arg line="-buildfile ftp.xml deploy-ftp -lib lib/ant"/>
</exec>
</target>
Now the master build file can be run without any special arguments and no modifications are required to the ant installation. It's nasty though, since the ftp task runs in a completely clean environment. None of the properties and paths from the master build file are available. Luckily I had all of these in a separate property file anyway, so I only needed a single import.
I would like to add a big thanks to Dan Dyer. Without your extensive explanation of what's going on behind the scenes, I wouldn't have found this solution.
Will this work assuming libs is directly under you project's base directory
<taskdef name="ftp" classname="org.apache.tools.ant.taskdefs.optional.net.FTP">
<classpath>
<pathelement location="${basedir}\libs\commons-net-1.4.0.jar"/>
</classpath>
</taskdef>
Your users all have ant installed on their machines but you can't / don't want to make them add the FTP jar? Can you bundle ant with your project make tasks that call YOUR ant bundle, with the jars placed so it'll work as follows?
<taskdef name="ftp" classname="org.apache.tools.ant.taskdefs.optional.net.FTP">
<classpath>
<pathelement location="\lib\commons-net-1.4.0.jar"/>
</classpath>
</taskdef>
<target name="testFtp">
<ftp server="blah" userid="foo" password="bar">
<fileset file="test.file" />
</ftp>
</target>