How to use asciidoctorj-diagram with Java or Groovy? - groovy

PlantUML is a great extension for Asciidoc, but I can't figure out how to use from my groovy code.
As far as I can see, the asciidoctorj-diaram module should be part of the current asciidoctorj-Release, so I guess I need no additional dependency. But my code which renders asciidoc fine, does not render the PlantUML diagrams. It says:
invalid style for open block: plantuml
Any idea what could be wrong? The asciidoctorj-diagram examples I find on the net all use the gradle-plugin :-|

Even if the library is part of the AsciidoctorJ project, there is a separate java library called: asciidoctorj-diagram (the java version of asciidoctor-diagram)
Are you sure that you have asciidoctorj-diagram on your classpath? Here the maven coordinates:
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-diagram</artifactId>
<version>1.3.1</version>
</dependency>
You also need to tell Asciidoctor that asciidoctor-diagram is required. See line <1> in the following plain java example:
public static void main(String[] args) {
org.asciidoctor.Asciidoctor asciidoctor =
org.asciidoctor.Asciidoctor.Factory.create();
asciidoctor.requireLibrary("asciidoctor-diagram"); // <1>
StringBuilder sb = new StringBuilder();
sb.append("== Diagrams\n");
sb.append("\n");
sb.append("[plantuml,auth-protocol]\n");
sb.append("....\n");
sb.append("Alice -> Bob: Authentication Request\n");
sb.append("Bob --> Alice: Authentication Response\n");
sb.append("\n");
sb.append("Alice -> Bob: Another authentication Request\n");
sb.append("Alice <-- Bob: another authentication Response\n");
sb.append("....\n");
String html = asciidoctor.convert(sb.toString(),
new java.util.HashMap<String, Object>());
System.out.println(html);
}
By the way, there is also a maven example: asciidoctor-diagram-example. But this example requires the asciidoctor-maven-plugin which is similar to the gradle plugin.

Related

Cucumber-serenity not inject Steps

I´m using cucumber-selenium to run some integration tests. I manage to create the feature file and the Test class. But once that I´m in my Give method I see that the ScenarioSteps(ProjectMemberSteps) class that I define to talk with the object page is null.
I was expecting to be injected like JBehave does.
public class OrderTest extends StepsLibrary {
#Steps ProjectMemberSteps projectManager;//This one is null
#Before
public void beforeScenarios() throws Exception {
initializeDemoUIServer();
}
#Given("I open the login page")
public void openLoginPage(){
projectManager.openLoginPage();
}
}
This is the Scenario runner class for the test
/**
* Serenity story for login.
*/
#RunWith(CucumberWithSerenity.class)
#CucumberOptions(features="src/test/resources/features/order/order.feature",
glue = Order.BEHAVIOUR_PACKAGE)
public class Order {
public static final String BEHAVIOUR_PACKAGE = "com.behaviour.steps.serenity";
}
This is class ProjectMemberSteps is under steps/serenity/ as the documentation suggest.
I´m using Maven, and the libraries that I´m using are
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-cucumber</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-junit</artifactId>
</dependency>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>core</artifactId>
<version>1.0.47</version>
</dependency>
Anyway this particular test I´m running with the IDE and not through Maven, but I was expecting that "ProjectMemberSteps" would be inject as JBehave use to do.
Any idea what´s wrong?
Regards.
I am also a newbie. I don't see any problem with your OrderTest.java class except it is unnecessarily extending a class called StepsLibrary. In Java-Cucumber, I don't extend any other class. Only exception is When
StepDefinition file(your OrderTest.java) delegates method calls to xxxxSteps.java class and which in turn delegates to xxxPageObject.java (which MUST extend PageObject class from Serenity import net.serenitybdd.core.pages.PageObject;)
I assume Before annotation is to repeat a scenario. Instead another alternative is Background keyword to be used in the feature file itself. I don't claim any advantage with this though.
Per me, Your Test Runner class should only give the package in which xxxxStepDefinitions.java resides, simply like glue = {"stepdefinitions"}, curly braces are optional I believe.
The rest looks perfectly OK to me. Including defining
#Steps ProjectMemberSteps projectManager;
Try one more time.

Jersey 2 - JAXB

Using Jersey 2 m13-3 in Tomcat 7, I'm trying to post XML and have JAXB automatically unmarshal it.
My method signature is something like:
#POST
#Consumes(MediaType.APPLICATION_XML)
#Produces( {"text/xml"})
public Response setFoo(
myXJC.generatedclass.Foo foo
)
I get a 400 bad request, but no exception (that I can find).
Testing with:
#POST
#Consumes(MediaType.APPLICATION_XML)
#Produces( {"text/xml"})
public Response setFoo() { ... }
I'm confident this method is being invoked in response to a request.
But as soon as I add arg myXJC.generatedclass.Foo, it isn't.
Do I need something special in my class which extends javax.ws.rs.core.Application to use JAXB? Something ResourceConfig related perhaps? Any extra jersey specific jars?
I see there is a jersey-media-moxy. I'd be happy to get it working with MOXy, but ideally it would also work with Sun/Oracle JAXB.
I've had a look at the source code of:
<dependency>
<groupId>org.glassfish.jersey.examples</groupId>
<artifactId>jaxb</artifactId>
<version>2.0-m13-3</version>
</dependency>
but I'm still having trouble.
Turns out that when I generated the classes from my XSD using XJC, I'd left an incorrect target namespace in there.
The XML I was posting was not namespace qualified, but the generated classes were expecting a namespace.
Once I fixed this, things worked fine.

Using JDK's JAXB without ns2 prefix

After having read all posts about this on Oracle forums, Stackoverflow, java.net I'm finally posting here.
I'm using JAXB to create XML files but the problem is that it adds the famous ns2 prefix before my elements, I have tried all the solutions no one worked for me.
java -version gives "1.6.0_37"
Solution 1 : Using package-info.java
I created the file in my package containing my #Xml* annotated classes with the following content :
#XmlSchema(
namespace = "http://mynamespace",
elementFormDefault = XmlNsForm.QUALIFIED,
xmlns = {
#XmlNs(namespaceURI = "http://mynamespace", prefix = "")
}
)
package com.mypackage;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Solution 2 : NamespacePrefixMapper
I created the following class and set the mapper to the marshaller :
// Change mapper to avoid ns2 prefix on generated XML
class PreferredMapper extends NamespacePrefixMapper {
#Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
return "";
}
}
NamespacePrefixMapper mapper = new PreferredMapper();
try {
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", mapper);
}
catch (PropertyException e) {
logger.info("No property for com.sun.xml.bind.namespacePrefixMapper found : " + e.getMessage());
}
With com.sun.xml.bind.namespacePrefixMapper nothing happens, with com.sun.xml.internal.bind.namespacePrefixMapper, it throws the exception.
I've also addded the maven dependency in my pom, but it seems that JRE version has a higher priority :
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.4</version>
</dependency>
Can you help me on this ?
PS : I can't include directly the jar in my classpath for build reasons.
PS2 : I can't use JDK7.
Thanks in advance.
Without the implementation of MOXy is not possible. JAXB if the preferred prefix is "", it generates a new one.
I had the same problem in the past, and I configured each prefix for each package-info.java.
NamespacePrefixMapper says in JAVADOC
null if there's no prefered prefix for the namespace URI.
In this case, the system will generate a prefix for you.
Otherwise the system will try to use the returned prefix,
but generally there's no guarantee if the prefix will be
actually used or not.
return "" to map this namespace URI to the default namespace.
Again, there's no guarantee that this preference will be
honored.
If this method returns "" when requirePrefix=true, the return
value will be ignored and the system will generate one"
else if use package-info
we know we can't bind to "", but we don't have any possible name at hand.
generate it here to avoid this namespace to be bound to "".
I hope I've given you all the answers about your question.
I had the same problem today. The production machine has Java 6 and when I deployed my application, I was getting the ns2 prefix. This is how I resolved it. Production server has only Java 1.6 patch 21
I made sure that I have a package-info.java file in my package where all the classes were generated using Jaxb. I checked it and the #XmlSchema was all auto generated, so I didn't mess with any of that. Don't use namespacemapper, that just confused me.
In my pom.xml file, I added jaxb-impl dependency:
com.sun.xml.bind
jaxb-impl
2.2.5-b04
and specified source and target as 1.6. Did a maven clean install and package and deployed into production, everything looks good.
Next step is to make sure that production machine is upgraded to Java 7. Hope this helps :)

Mockito methods are not accessible

I have mockito setup on my project with this maven lines:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.8.5</version>
<scope>test</scope>
</dependency>
I have no problems to use the #Mock annotation but I can't access and use mockito methods like:
when(someMock.someMethod()).thenReturn();
Eclipse just does not recognize them.
Please help.
Try calling Mockito.when(foo.getBar()).thenReturn(baz) and Mockito.verify(foo).getBar(), which won't rely on static imports. Unlike the #Mock annotation, which is technically a class, when and verify are static methods on the Mockito class.
Once you have that working, then try the static imports to which David alluded:
import static org.mockito.Mockito.when; // ...or...
import static org.mockito.Mockito.*; // ...with the caveat noted below.
This will then allow you to use Mockito.when without specifying the Mockito class. You can also use a wildcard, as so, but per this SO answer the Java docs recommend using wildcards sparingly--especially since it can break if a similarly-named static method is ever added to Mockito later.
Adding import org.mockito.*; is insufficient because that adds all classes in the org.mockito package, but not the methods on org.mockito.Mockito.
For Eclipse in particular, you can add a static import by putting the cursor on the when part of Mockito.when and pressing Control-Shift-M ("Add import"). You can also add org.mockito.Mockito to your Favorites (Window > Preferences > Java > Editor > Content Assist > Favorites > New Type) so that all Mockito static methods show up in your Ctrl-Space content assist prompt even if you haven't imported them specifically. (You may also want to do this for org.mockito.Matchers, which are technically available on org.mockito.Mockito via inheritance, but may not show up in Eclipse for that reason.)
Kotlin syntax - dont forget the ` ` backticks:
import org.mockito.Mockito.`when`
`when`(someMock.someMethod()).thenReturn();

No suitable classloader found for grab

I have this at the beginning of a class:
#Grab(group = 'org.ccil.cowan.tagsoup', module = 'tagsoup', version = '1.2')
class MyClass{...
I'm trying to unit test this class, but whenever I try to run JUnit 4 tests, I get this error:
Caused by: java.lang.RuntimeException: No suitable ClassLoader found for grab
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:77)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:102)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:52)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:190)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:198)
at groovy.grape.GrapeIvy.chooseClassLoader(GrapeIvy.groovy:163)
at groovy.grape.GrapeIvy$chooseClassLoader.callCurrent(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:44)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149)
at groovy.grape.GrapeIvy.grab(GrapeIvy.groovy:227)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:225)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:51)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:44)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:153)
at groovy.grape.GrapeIvy.grab(GrapeIvy.groovy:216)
at groovy.grape.Grape.grab(Grape.java:131)
at groovy.grape.Grape$grab.callStatic(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:165)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:173)
at ammoscanner.AmmoScanner.<clinit>(AmmoScanner.groovy)
... 30 more
Any ideas? I'm using groovy 1.7.5
The Problem
Looking at the source code, this exception is thrown whenever the supplied ClassLoader's name (or it's superclasses) is not groovy.lang.GroovyClassLoader or org.codehaus.groovy.tools.RootLoader. i.e. The target classloader must be an instance of the aforementioned classes (a bit restrictive IMHO).
A Solution
Currently I don't know how to configure a specific classloader using #Grape/#Grab/#GrabConfig annotations. The closest would be to use #GrabConfig(systemClassLoader=true), and ensure the System classloader is an instance of one of the above ClassLoader classes.
If anyone does know, please let me know (and I'll update this answer).
A Workaround
The following code will programmatically download your Grapes, and load them into the supplied GroovyClassLoader (admittedly, not quite what you want).
def loadGrapes(){
ClassLoader classLoader = new groovy.lang.GroovyClassLoader()
Map[] grapez = [[group : 'org.ccil.cowan.tagsoup', module : 'tagsoup', version : '1.2']]
Grape.grab(classLoader: classLoader, grapez)
println "Class: " + classLoader.loadClass('org.ccil.cowan.tagsoup.jaxp.SAXParserImpl')
}
Using #Grab makes code untestable, at least as of 01/26/2011.
Solution that worked for me (both for running tests for scripts using #Grab in IntelliJ and via Maven):
Reference the dependencies used via #Grab in your Maven pom.xml file (this is useful anyway for better coding experience):
E.g. I have the following #Grab in my Groovy script:
#Grab(group='info.picocli', module='picocli', version='4.6.1')
So I add the following Maven dependency:
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli</artifactId>
<version>4.6.1</version>
</dependency>
Add an optional dependency on ivy in your Maven pom.xml file (needed to handle #Grab properly in your IDE):
<dependency>
<groupId>org.apache.ivy</groupId>
<artifactId>ivy</artifactId>
<version>${ivy.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
In your test code, set groovy.grape.enable system property to false. This is the main and crucial part of the solution - it disables #Grab annotation processing for the script, but remember we already have those dependencies referenced in our Maven pom.xml file:
static {
System.setProperty("groovy.grape.enable", "false")
}
#Test
void test() {
MainScript.call()
}
The downside of the solution is that you have to duplicate your dependencies in #Grab and Maven pom.xml file but again, if you develop a Groovy script you oftentimes already do so to improve your coding experience (get better code highlights etc).
I assume you've tried adding
#GrabConfig(systemClassLoader=true)
like so:
#Grapes([
#Grab(group = 'org.ccil.cowan.tagsoup', module = 'tagsoup', version = '1.2'),
#GrabConfig( systemClassLoader=true )
])
class MyClass{...
If you are not using systemClassLoader=true then it seems your IDE is not rrunning the code with a groovy compiler, you can check that with a simple groovy class that outputs the class name of its classloader. I would guess it tries to compile the groovy classes and run them with a non-groovy classloader.
See also this answer to General error during conversion: No suitable ClassLoader found for grab. Also this blog post explains more about running pre-compiled groovy classes with the stock classloader.
Add the plugin snapshot update site for Kepler.
This seems to solve the "..no suitable classloader problem". Unfortunately, I still had to add the grape repo to the classpath for the project after this.
There's one more solution for testing a class with #Grab annotation:
Extract an interface from this class.
Create another class which implements its interface. Move the #Grab annotation to this class. Then make this class a simple wrapper, which just passes all the messages to the original class.
Run the tests against your original class.
Whenever you need to have a version #Grab, use the wrapper.
There is a solution to this!
You can use Groovy's metaprogramming to override the methods responsible for determining if the class loader is an instance of groovy.lang.GroovyClassLoader or org.codehaus.groovy.tools.RootLoader.
Because of this Groovy bug, you cannot override the private methods using metaprogramming, otherwise you could go ahead and change the isValidTargetClassLoaderClass method by doing this:
GrapeIvy.metaClass.isValidTargetClassLoaderClass = { Class loaderClass ->
return (loaderClass != null)
}
However, isValidTargetClassLoaderClass is called by isValidTargetClassLoader (another private method), which is called by chooseClassLoader, which is a public method, which can be overridden using metaprogramming:
GrapeIvy.metaClass.chooseClassLoader = { Map args ->
def loader = args.classLoader
if (loader?.class == null) {
loader = (args.refObject?.class
?: ReflectionUtils.getCallingClass(args.calleeDepth?:1)
)?.classLoader
while (loader && loader?.class == null) {
loader = loader.parent
}
if (loader?.class == null) {
throw new RuntimeException("No suitable ClassLoader found for grab")
}
}
return loader
}
All I did was replace any calls to !isValidTargetClassLoader with loader?.class == null.
Now, I am using Spock, so I put this code in my setupSpec method in my test class. However if you are using JUnit, I would imagine it would want to go in the method annotated with #BeforeClass.
Here is an example of it working with Spock (notice IntelliJ showing it about to return a class loader that would normally throw an exception:

Resources