How can I debug a Doclet in Java 10? - java

Using Java 8, it is easy to debug a Doclet: How can I debug a Doclet in Eclipse?
But how to achieve this in Java 10 and subsequent versions? Calling
jdk.javadoc.internal.tool.Main.execute(javadocArgs);
throws an Exception:
Exception in thread "main" java.lang.IllegalAccessError: class my.BDoclet (in unnamed module #0x1f36e637) cannot access class jdk.javadoc.internal.tool.Main (in module jdk.javadoc) because module jdk.javadoc does not export jdk.javadoc.internal.tool to unnamed module #0x1f36e637

The javadocArgs is an array containing each argument as a single entry:
String[] docletArgs = new String[]{
"-doclet", LatexDoclet.class.getName(),
"-docletpath", "target/classes/",
"-sourcepath", "src/test/java/",
LatexDoclet.class.getPackageName()
};
DocumentationTool docTool = ToolProvider.getSystemDocumentationTool();
docTool.run(System.in, System.out, System.err, docletArgs);

Example based on Slaw's comment:
String[] javadocArgs = new String[] {...}
ServiceLoader<Tool> toolService = ServiceLoader.load(Tool.class);
Optional<Tool> javadocOpt = toolService.stream().map(p -> p.get()).filter(t -> t.name().equals("javadoc")).findFirst();
javadocOpt.orElseThrow().run(System.in, System.out, System.err, javadocArgs);

The same, a bit more elegantly:
//import javax.tools.*;
String[] args = new String[]{"-doclet " + MyDoclet.class.getName()};
DocumentationTool docTool = ToolProvider.getSystemDocumentationTool();
docTool.run(System.in, System.out, System.err, args);
However, it's not clear to me what the "args" should be because it doesn't work and produces:
javadoc: error - invalid flag: -doclet ...MyDoclet

Related

Importing a groovy file from one package to another groovy file in another package

I have a child java project which has groovy files added in classpath using eclipse. Parent java project triggers some functionality in child which uses Groovy library to run the scripts. So import works fine in eclipse environment with opened child project but if I run it from command line or if I close child project then I get groovy compilation error at import statement. How can I resolve this ? I want to avoid using evaluate() method.
Following is my master groovy:
package strides_business_script
abstract class Business_Script extends Script {
//some stuff
}
Following is the another groovy:
import static strides_business_script.StridesBusiness_Script.*;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
String Key = Part_Product_PartDetails
boolean containsData = checkIncomingMessage(Key)
if(containsData) {
def edgeKeyList = [PPR]
JSONArray partDetails = appendEdgeValueToMsg(edgeKeyList,Key,vertex,messageIterator);
//deleteMessages(Key);
JSONObject jsonObject = constructInfoWithPropertyJSON("NAME,PRODUCTTYPE,FGTYPE,UOM,ITEMCLASSIFICATIONBYMARKET");
jsonObject.put("PARTS",partDetails);
send(Product_AggPO_ProductDetails,convertJSONToString(jsonObject));
}
Edit:
My master script Business_Script.groovy resides in scripts/strides_business_script/ folder. All other scripts are in scripts/StridesComputationScripts/ folder and they import the Business_Script.groovy.
I run the application with remote debugging enabled like this:
java -cp "./lib/*:./scripts/strides_business_script/Business_Script.groovy" -Xdebug -Xrunjdwp:transport=dt_socket,address=6969,server=y -Dhibernate.cfg.xml.path=./conf/hibernate.cfg.xml -Dlog4j.configuration=file:./conf/log4j.properties com.biglabs.dataExtractor.dataDump.DataDumpDriver 7
and here I am trying to parse all computation scripts.
for (String scriptName : files) {
Script script = groovyShell.parse(new File(
SCRIPT_PLACED_AT + Constants.SLASH
+ SCRIPT_FILE_FOLDER + Constants.SLASH
+ scriptName));
scriptMping.put(scriptName, script);
}
It throws following exception while parsing using groovy shell:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/home/manoj/strides/release/strides/scripts/StridesComputationScripts/PRODUCT-script.groovy: 2: unable to resolve class strides_business_script.StridesBusiness_Script
# line 2, column 1.
import static strides_business_script.Business_Script.*;
^
/home/manoj/strides/release/strides/scripts/StridesComputationScripts/PRODUCT-script.groovy: 2: unable to resolve class strides_business_script.StridesBusiness_Script
# line 2, column 1.
import static strides_business_script.Business_Script.*;
^
2 errors
Fixed it by adding script path in comiler configuration:
CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
String path = SCRIPT_PLACED_AT;
if(!SCRIPT_PLACED_AT.endsWith("/")){
path = path+ "/";
}
compilerConfiguration.setClasspath(path);
GroovyShell groovyShell = new GroovyShell(
compilerConfiguration);
for (String scriptName : files) {
Script script = groovyShell.parse(new File(
SCRIPT_PLACED_AT + Constants.SLASH
+ SCRIPT_FILE_FOLDER + Constants.SLASH
+ scriptName));
scriptMping.put(scriptName, script);
}

Eclipse XML Parser "Providers" conflicting with rt.jar

Please note: Although there are several questions on SO that paste in a similar exception & stack trace, this question is definitely not a dupe of any of them, as I'm trying to understand where my classloading is going awry.
Hi, Java 8/Groovy 2.4.3/Eclipse Luna here. I'm using the BigIP iControl Java client (for controlling a powerful load balancer programmatically) which in turn uses Apache Axis 1.4. In its use of Axis 1.4 I am getting the following stacktrace (from Eclipse console):
Caught: javax.xml.parsers.FactoryConfigurationError: Provider for javax.xml.parsers.DocumentBuilderFactory cannot be found
javax.xml.parsers.FactoryConfigurationError: Provider for javax.xml.parsers.DocumentBuilderFactory cannot be found
at org.apache.axis.utils.XMLUtils.getDOMFactory(XMLUtils.java:221)
at org.apache.axis.utils.XMLUtils.<clinit>(XMLUtils.java:83)
at org.apache.axis.configuration.FileProvider.configureEngine(FileProvider.java:179)
at org.apache.axis.AxisEngine.init(AxisEngine.java:172)
at org.apache.axis.AxisEngine.<init>(AxisEngine.java:156)
at org.apache.axis.client.AxisClient.<init>(AxisClient.java:52)
at org.apache.axis.client.Service.getAxisClient(Service.java:104)
at org.apache.axis.client.Service.<init>(Service.java:113)
at iControl.LocalLBPoolLocator.<init>(LocalLBPoolLocator.java:21)
at iControl.Interfaces.getLocalLBPool(Interfaces.java:351)
at com.me.myapp.F5Client.run(F5Client.groovy:27)
Hmmm, let's have a look at that XMLUtils.getDOMFactory method:
private static DocumentBuilderFactory getDOMFactory() {
DocumentBuilderFactory dbf;
try {
dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
}
catch( Exception e ) {
log.error(Messages.getMessage("exception00"), e );
dbf = null;
}
return( dbf );
}
OK, LN 221 is that call to DocumentBuilderFactory.newInstance() so let's have a look at it:
public static DocumentBuilderFactory newInstance() {
return FactoryFinder.find(
/* The default property name according to the JAXP spec */
DocumentBuilderFactory.class, // "javax.xml.parsers.DocumentBuilderFactory"
/* The fallback implementation class name */
"com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
}
The plot thickens! Now let's take a final look at FactoryFinder.find:
static <T> T find(Class<T> type, String fallbackClassName)
throws FactoryConfigurationError
{
final String factoryId = type.getName();
dPrint("find factoryId =" + factoryId);
// lots of nasty cruft omitted for brevity...
// Try Jar Service Provider Mechanism
T provider = findServiceProvider(type);
if (provider != null) {
return provider;
}
if (fallbackClassName == null) {
throw new FactoryConfigurationError(
"Provider for " + factoryId + " cannot be found"); // <<-- Ahh, here we go
}
dPrint("loaded from fallback value: " + fallbackClassName);
return newInstance(type, fallbackClassName, null, true);
}
So if I'm interpreting this right, it's throwing the FactoryConfigurationError because it can't find the main "provider class" (whatever that means) and no fallback has been specified. But hasn't it?!? The call to FactoryFinder.find included the non-null "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl" string argument. This has me suspicious that something is really wonky with my classpath, and that I have a rogue DocumentBuilderFactory (not the one defined in rt.jar/javax/xml/parsers) somewhere in my code that is passing a NULL arg to this finder method.
But that doesn't make sense either, because Axis 1.4 doesn't appear (at least according to Maven repo) to have any dependencies...which means the only "provider" for javax.xml.* would be the rt.jar. Unless, perhaps, Eclipse is mucking things up somehow? I'm so confused, please help :-/
Update
This is definitely an Eclipse issue. If I package my app as an executable JAR and run it from the command line I don't get this exception.

Static Java function imported with rJava doesn't work with tm_map()

I've prepared a class with a static method in Java 6, which I've exported to a JAR file:
package pl.poznan.put.stemutil;
public class Stemmer {
public static String stemText(String text) {
Set<String> c = new HashSet<String>();
...
return StringUtils.join(c, " ");
}
}
I import it to R with following code:
require(rJava)
.jinit("java/stem-util.jar")
stem = J("pl.poznan.put.stemutil.Stemmer")$stemText
Then, when I call it directly it works, e.g:
> stem("płotkami")
[1] "płotek płotka"
But when I'll try to use it with tm_map() function, something goes wrong:
> vc = VCorpus(vs, readerControl = list(language = "pl"))
> vc[[1]]
<<PlainTextDocument (metadata: 7)>>
mirki mirkówny zaczynam wolne jutra ( ͡° ͜ʖ ͡°) #pijzwykopem #piwozlidla
> vc = tm_map(vc, stem)
Komunikat ostrzegawczy:
In mclapply(content(x), FUN, ...) :
all scheduled cores encountered errors in user code
> vc[[1]]
[1] "Error in FUN(X[[1L]], ...) : \n Sorry, parameter type `NA' is ambiguous or not supported.\n"
attr(,"class")
[1] "try-error"
attr(,"condition")
<simpleError in FUN(X[[1L]], ...): Sorry, parameter type `NA' is ambiguous or not supported.>
What am I doing incorrectly?
Finally adding mc.cores parameter has worked for me. However, It's more a workaround, than a proper solution.
vc = tm_map(vc, content_transformer(stem), mc.cores=1)

Loading classes to application from file system at runtime

I have an application which deals with jdbc. It supposes to be used in any PC where there is JRE, but it does not suppose that use will use -cp command line or change his/her classpath variables. So the user has my application, JRE and a jdbc driver somewhere in file system. Now he or she enters a database connection information including path to jdbc driver jar and then make sql request. The problem is that I don't now how to make jdbc driver classes to be accessible in this application. The same way as the user explicitly add a driver to classpath.
I just altered part of the miks answer for your other posting.
Executing the following code got me a success.
import java.io.File;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader;
public class URLClassLoaderSample {
public static void main( String [] args ) throws Exception {
File f = new File( "/home/ravinder/Desktop/mysql-connector-java-5.1.18-bin.jar" );
URLClassLoader urlCl = new URLClassLoader( new URL[] { f.toURL() }, System.class.getClassLoader() );
Class mySqlDriver = urlCl.loadClass( "com.mysql.jdbc.Driver" );
System.out.println( mySqlDriver.newInstance() );
System.out.println( "Is this interface? = " + mySqlDriver.isInterface() );
Class interfaces[] = mySqlDriver.getInterfaces();
int i = 1;
for( Class _interface : interfaces ) {
System.out.println( "Implemented Interface Name " + ( i++ ) + " = " + _interface.getName() );
} // for(...)
Constructor constructors[] = mySqlDriver.getConstructors();
for( Constructor constructor : constructors ) {
System.out.println( "Constructor Name = " + constructor.getName() );
System.out.println( "Is Constructor Accessible? = " + constructor.isAccessible() );
} // for(...)
} // psvm(...)
} // class URLClassLoaderSample
Output seen is as follows:
com.mysql.jdbc.Driver#60aeb0
Is this interface? = false
Implemented Interface Name 1 = java.sql.Driver
Constructor Name = com.mysql.jdbc.Driver
Is Constructor Accessible? = false
And I don't understand what I should with log4jClass variable in my case *(com.mysql.jdbc.Driver)
Let me hope now you got it.
The best solution in this instance would be to distribute the required driver with your application and include either an executable wrapper or a shell script that sets the required variables accordingly. That allows the user to use it out of the box without having to mess with any complicated configuration and also doesn't require them to download any additional files.
Well, jdbc uses Class.forName("org.postgresql.Driver"); to load the driver. So once, you have the jar file, and have added it to the class-path, this part is easy. Just keep a hash of driver fqn classnames to jar file names. Or you can scan the jar for the Driver class.
Here's a convienent answer to how to add the jar file to the classpath once you find it.

bean validation- hibernate error

I am getting following exception when trying to run my command line application:
java.lang.ExceptionInInitializerError
at org.hibernate.validator.engine.ConfigurationImpl.<clinit>(ConfigurationImpl.java:52)
at org.hibernate.validator.HibernateValidator.createGenericConfiguration(HibernateValidator.java:43)
at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:269)
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -2
at java.lang.String.substring(String.java:1937)
at org.hibernate.validator.util.Version.<clinit>(Version.java:39)
... 34 more
Am I doing anything wrong? Please suggest.
This is strange. I pasted the relevant parts of the static initialization block of o.h.v.u.Version in a class with a main and added some poor man's logging traces:
public class VersionTest {
public static void main(String[] args) {
Class clazz = org.hibernate.validator.util.Version.class;
String classFileName = clazz.getSimpleName() + ".class";
System.out.println(String.format("%-16s: %s", "classFileName", classFileName));
String classFilePath = clazz.getCanonicalName().replace('.', '/') + ".class";
System.out.println(String.format("%-16s: %s", "classFilePath", classFilePath));
String pathToThisClass = clazz.getResource(classFileName).toString();
System.out.println(String.format("%-16s: %s", "pathToThisClass", pathToThisClass));
// This is line 39 of `org.hibernate.validator.util.Version`
String pathToManifest = pathToThisClass.substring(0, pathToThisClass.indexOf(classFilePath) - 1)
+ "/META-INF/MANIFEST.MF";
System.out.println(String.format("%-16s: %s", "pathToManifest", pathToManifest));
}
}
And here the output I get when running it:
classFileName : Version.class
classFilePath : org/hibernate/validator/util/Version.class
pathToThisClass : jar:file:/home/pascal/.m2/repository/org/hibernate/hibernate-validator/4.0.2.GA/hibernate-validator-4.0.2.GA.jar!/org/hibernate/validator/util/Version.class
pathToManifest : jar:file:/home/pascal/.m2/repository/org/hibernate/hibernate-validator/4.0.2.GA/hibernate-validator-4.0.2.GA.jar!/META-INF/MANIFEST.MF
In your case, the StringIndexOutOfBoundsException: String index out of range: -2 suggests that:
pathToThisClass.indexOf( classFilePath )
is returning -1, making the pathToThisClass.substring(0, -2) call indeed erroneous.
And this means that org/hibernate/validator/util/Version.class is somehow not part of the pathToThisClass that you get. I don't have a full explanation but this must be related to the fact that you're using One-Jar.
Could you run the above test class and update your question with the output?
So, as you use One-JAR, the problem probably is in incompatibility between One-JAR and Hibernate Validator. However, in the latest version of One-JAR (0.97) it works fine, therefore use the latest version.

Categories