Calling IDX MLS SOAP APIs of ihomefinder from Java Spring MVC - java

I want to use ihomefinder's test APIs to get the data and insert it into my own database. I am using Spring MVC and the link provided by them which I configured in my pom.xml to get the data is http://axisws.idxre.com:8080/axis2/services/IHFPartnerServices?wsdl.
From various searches I found that all the provided APIs are in package com.ihomefinder.api so I included it too into the pom.xml
Here is the pom.xml code:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-ws</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.13.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<generatePackage>com.ihomefinder.api</generatePackage>
<schemas>
<schema>
<url>http://axisws.idxre.com:8080/axis2/services/IHFPartnerServices?wsdl</url>
</schema>
</schemas>
</configuration>
</plugin>
</plugins>
</build>
Now I am trying to login with the test username and password provided by them, but to hit the login service I need to create the Object of Request class which is not found in the package com.ihomefinder.api.
Here is the java code I am using to make the request:
import javax.xml.bind.JAXBElement;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.client.core.SoapActionCallback;
import com.ihomefinder.api.Login;
import com.ihomefinder.api.ObjectFactory;
public class IdxMls extends WebServiceGatewaySupport {
public void main() {
// TODO Auto-generated method stub
ObjectFactory objectFactory = new ObjectFactory();
JAXBElement<String> user = objectFactory.createLoginUsername("username");
JAXBElement<String> pass = objectFactory.createLoginPassword("password");
Login login = new Login();
login.setUsername(user);
login.setPassword(pass);
Integer int1 = (Integer) getWebServiceTemplate().marshalSendAndReceive(login, new SoapActionCallback("http://axisws.idxre.com:8080/axis2/services/Login"));
System.out.println(int1);
}
public static void main(String[] args) {
IdxMls idxMls = new IdxMls();
idxMls.main();
}
}
I think the above code is not perfect some things are really missing. So can anybody help me to correct the code by which I can get the response from the API?

It looks like you're using our partner API soap client. Our most current Reseller API is a REST API, and the entry point URL is:
https://www.idxhome.com/restServices/reseller/login
Documentation for the reseller API is not publicly posted at this time. Please email us at support#ihomefinder.com, and we would be happy to provide you the documentation.

Related

Java Maven OpenApi (3.0) Codegen is generating unwanted test file, how to remove that?

I am using OpenApi(3.0) for api definition and the openapi-generator-maven-plugin which generates files for me (api objects + endpoints).
Its however generating a test file in the build folder that I do not want. Its called 'OpenApiGeneratorApplicationTests'. It always blocks my compilation bc in the 'target' (=build) folder I do not have the right Spring Boot setup.
How can I avoid the generation of this test file?
This is my maven config:
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>6.0.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/ApiDef.yaml</inputSpec>
<generatorName>spring</generatorName>
<modelPackage>${clientPackage}.model</modelPackage>
<invokerPackage>${clientPackage}.invoker</invokerPackage>
<apiPackage>${clientPackage}.api</apiPackage>
<generateApis>true</generateApis>
<generateApiTests>false</generateApiTests>
<generateModelTests>false</generateModelTests>
<configOptions>
<delegatePattern>true</delegatePattern>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
I've encountered today the same issue. So long story short:
By default the generator maven plugin for Spring will generate the 'invoker' - which by implementation is actually a #SpringBootApplication starter class.
#SpringBootApplication
#ComponentScan(basePackages = {"com.mypackage.invoker", "com.mypackage.api" , "org.openapitools.configuration"})
public class OpenApiGeneratorApplication {
public static void main(String[] args) {
SpringApplication.run(OpenApiGeneratorApplication.class, args);
}
#Bean
public Module jsonNullableModule() {
return new JsonNullableModule();
}
}
and will also generate the associated test class OpenApiGeneratorApplicationTests
#SpringBootTest
class OpenApiGeneratorApplicationTests {
#Test
void contextLoads() {
}
}
The problem here is that the src/test/com/mypackage/invoker/OpenApiGeneratorApplicationTests.java, and actually the whole package under test is marked as source, not as test-source and in my case this will result in compile time errors (since the test-scoped dependencies are not found).
I managed to get around it by configuring the maven plugin with
<configOptions>
<interfaceOnly>true</interfaceOnly>
...
</configOptions>
which will skip the generation of the SpringBootApplication and the associated Tests.
I've also submitted a ticket to the OpenApi Generator project's github for marking the

How to write an annotation/aspect to not enter a method but return null if a given condition is false?

I currently have a requirement where I need to return null from 100s of methods if a given condition is false. I was thinking of using Java Annotations or Spring Aspects for this so that I don't have to write that if-else block of code everywhere. Any idea as to how we can do this using Java Annotations or Spring Aspects?
Any pointers might be helpful.
If I get you correctly, Spring #Conditional annotation is what you want.
You create some public class that implements Spring's Condition interface:
public class Test implements Condition {
...
}
Then you use the forementioned annotation with the parameter which takes as an argument that public class.
#Conditional(Test.class)
public Object someMethod(boolean context){
/*and so do some logics; if the value of 'context' variable is false, you can return
null; otherwise, just return like this*/
return new someMethodImpl1();
}
Hope I helped. And I'm glad of any kind of corrections. Cheers!
Without spring you could use pure AspectJ:
Demo.java : example of the method we want to modify
public class Demo {
public String boom(String base) {
return base;
}
}
DemoAspect.aj : configuration file. Getting started. In AspectJ, pointcuts pick out certain join points in the program flow. To actually implement crosscutting behavior, we use advice. Advice brings together a pointcut (to pick out join points) and a body of code (to run at each of those join points): before, around, after...
public aspect DemoAspect {
pointcut callBoom(String base, Demo demo) :
call(String Demo.boom(String)) && args(base) && target(demo);
String around(String base, Demo demo) : callBoom(base, demo){
if ("detonate".equals(base)) {
return "boom!";
} else {
return proceed(base, demo);
}
}
}
DemoTest.java
public class DemoTest {
#Test
void name() {
Demo demo = new Demo();
assertEquals("boom!", demo.boom("detonate"));
assertEquals("fake", demo.boom("fake"));
}
}
Add dependencies into pom.xml
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
And plugin, pay attention to the versions. For example 1.11 plugin expects 1.8.13 libraries.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.11</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>UTF-8 </encoding>
</configuration>
<executions>
<execution>
<goals>
<!-- use this goal to weave all your main classes -->
<goal>compile</goal>
<!-- use this goal to weave all your test classes -->
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
Good example with more details, Baeldung. Official documentation.

Web service (JAX-WS) client in different package

Should look like a stupid question, but I have the following problem.
There's an external web service, WSDL is available. My task is to call it's methods from another enterprise application (running on WebSphere 8.5)
Using Rational Application Developer, I generated Web service client classes into the application's project, specifying the application's package, which DIFFERS from the web service's one. Web service's method returns a POJO, which is a wrapper for ArrayList.Then I make a call to web service, using generated calsses in the following way:
package com.mycompany.services.external;
import com.mycompany.services.external.client.SomeCommonService;
import com.mycompany.services.external.client.SomeCommonServiceService;
import com.mycompany.services.external.client.IdsList;
final QName COMMONSERVICE_QNAME = new QName("http://webService.othercompany.com/", "SomeCommonServiceService");
String strUrl = "http://....";
String query = "/universal [#Barcode=\"000111\"]";
URL serviceUrl = new URL(strUrl);
SomeCommonServiceService service=new SomeCommonServiceService(serviceUrl, COMMONSERVICE_QNAME);
SomeCommonService port = service.getSomeCommonServicePort();
IdsList itemsIds = port.getItemsIdsByQuery(query);
And as a result the last line of code, where the method is invoked, causes an error:
[1/17/17 21:55:39:758 MSK] 00000497 SystemErr R CIWEB Error:
[admin(unknown) # 10.253.32.24]
com.ibm.ecm.util.PluginUtil.invokeService()
javax.xml.ws.WebServiceException: javax.xml.bind.JAXBException:
com.mycompany.services.external.client.IdsList is not known to this
context
Taking a look into the generated package-info.java the following mapping can be seen:
#javax.xml.bind.annotation.XmlSchema(namespace = "http://webService.othercompany.com/")
package com.mycompany.services.external.client;
If I leave original option (not changing default package) while generating client - the same problem and the same error. But in this case, if I pack generated client into a separate JAR and use it as a shared library for my application on WebSphere server - then all works fine! But that's not acceptable for some reasons.
Could somebody be so pleasant to hepl me solve the problem?
I used to work with Web Services Base on WSDL:
Example: http://www.dgii.gov.do/wsMovilDGII/WSMovilDGII.asmx?wsdl
Of course using MAVEN, I use this pluging
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.1.5</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${basedir}/src/main/java/</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>http://www.dgii.gov.do/wsMovilDGII/WSMovilDGII.asmx?wsdl</wsdl>
<packagenames>
<packagename>com.hectorvent.consultadgii</packagename>
</packagenames>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>

Unable to run "Hello World" Java client of Elastic-Search

I am unable to run a very basic program of creating a "Hello World" java client of Elastic-Search.
The documentation is extremely terse about what to do in such cases.
Here is my code:
find . -type f
./pom.xml
./src/main/java/examples/EsRoutingNodeClient.java
Both files are shown below.
Java file containing the code:
package examples;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.node.NodeBuilder;
public class EsRoutingNodeClient
{
private static final String ZEN_DISCOVERY_UNICAST_HOSTS = "[\"10.10.10.10:9200\"]"; // Used an actual ES master node's IP here
private static final String ES_PATH_HOME = "/Users/appuser/work/software/elasticsearch/dummy-path-home/";
private static final String ES_CLUSTER_NAME = "my-cluster";
private Client client;
private void createEsClient ()
{
Settings settings = Settings.settingsBuilder()
.put("http.enabled", false)
.put("discovery.zen.ping.multicast.enabled", false)
.put("discovery.zen.ping.unicast.hosts", ZEN_DISCOVERY_UNICAST_HOSTS)
.put("discovery.zen.minimum_master_nodes", 1)
.put("path.home", ES_PATH_HOME)
.build();
client =
NodeBuilder.nodeBuilder()
.settings(settings)
.clusterName(ES_CLUSTER_NAME)
.data(false)
.client(true)
.node().client();
}
public EsRoutingNodeClient ()
{
createEsClient();
}
public static void main (String args[])
{
new EsRoutingNodeClient();
}
}
pom.xml:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>examples</groupId>
<artifactId>es-node-client</artifactId>
<version>0.0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>es-node-client</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<configuration />
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<excludes>
<exclude>org.slf4j:*</exclude>
<exlcude>com.esotericsoftware.kryo:kryo:*</exlcude>
</excludes>
</artifactSet>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>examples.EsRoutingNodeClient</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Finally I run it as follows:
mvn clean package
java -jar target/es-node-client-0.0.3-SNAPSHOT.jar
And the exception I get is:
194) Error injecting constructor, java.lang.IllegalStateException: This is a proxy used to support circular references involving constructors. The object we're proxying is not constructed yet. Please wait until after injection has completed to use this object.
at org.elasticsearch.node.service.NodeService.<init>(Unknown Source)
while locating org.elasticsearch.node.service.NodeService
for parameter 5 at org.elasticsearch.action.admin.cluster.node.stats.TransportNodesStatsAction.<init>(Unknown Source)
while locating org.elasticsearch.action.admin.cluster.node.stats.TransportNodesStatsAction
for parameter 2 at org.elasticsearch.cluster.InternalClusterInfoService.<init>(Unknown Source)
while locating org.elasticsearch.cluster.InternalClusterInfoService
while locating org.elasticsearch.cluster.ClusterInfoService
for parameter 3 at org.elasticsearch.cluster.routing.allocation.AllocationService.<init>(Unknown Source)
while locating org.elasticsearch.cluster.routing.allocation.AllocationService
for parameter 3 at org.elasticsearch.cluster.metadata.MetaDataCreateIndexService.<init>(Unknown Source)
while locating org.elasticsearch.cluster.metadata.MetaDataCreateIndexService
for parameter 5 at org.elasticsearch.snapshots.RestoreService.<init>(Unknown Source)
while locating org.elasticsearch.snapshots.RestoreService
Caused by: java.lang.IllegalStateException: This is a proxy used to support circular references involving constructors. The object we're proxying is not constructed yet. Please wait until after injection has completed to use this object.
at org.elasticsearch.common.inject.internal.ConstructionContext$DelegatingInvocationHandler.invoke(ConstructionContext.java:103)
at com.sun.proxy.$Proxy11.setNodeService(Unknown Source)
at org.elasticsearch.node.service.NodeService.<init>(NodeService.java:77)
at sun.reflect.GeneratedConstructorAccessor4.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.elasticsearch.common.inject.DefaultConstructionProxyFactory$1.newInstance(DefaultConstructionProxyFactory.java:50)
at org.elasticsearch.common.inject.ConstructorInjector.construct(ConstructorInjector.java:86)
at org.elasticsearch.common.inject.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:104)
at org.elasticsearch.common.inject.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:47)
at org.elasticsearch.common.inject.InjectorImpl.callInContext(InjectorImpl.java:887)
at org.elasticsearch.common.inject.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:43)
at org.elasticsearch.common.inject.Scopes$1$1.get(Scopes.java:59)
at org.elasticsearch.common.inject.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:46)
at org.elasticsearch.common.inject.SingleParameterInjector.inject(SingleParameterInjector.java:42)
... more such lines
at org.elasticsearch.common.inject.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:46)
at org.elasticsearch.common.inject.InjectorBuilder$1.call(InjectorBuilder.java:201)
at org.elasticsearch.common.inject.InjectorBuilder$1.call(InjectorBuilder.java:193)
at org.elasticsearch.common.inject.InjectorImpl.callInContext(InjectorImpl.java:880)
at org.elasticsearch.common.inject.InjectorBuilder.loadEagerSingletons(InjectorBuilder.java:193)
at org.elasticsearch.common.inject.InjectorBuilder.injectDynamically(InjectorBuilder.java:175)
at org.elasticsearch.common.inject.InjectorBuilder.build(InjectorBuilder.java:110)
at org.elasticsearch.common.inject.Guice.createInjector(Guice.java:93)
at org.elasticsearch.common.inject.Guice.createInjector(Guice.java:70)
at org.elasticsearch.common.inject.ModulesBuilder.createInjector(ModulesBuilder.java:46)
at org.elasticsearch.node.Node.<init>(Node.java:200)
at org.elasticsearch.node.Node.<init>(Node.java:128)
at org.elasticsearch.node.NodeBuilder.build(NodeBuilder.java:145)
at org.elasticsearch.node.NodeBuilder.node(NodeBuilder.java:152)
at examples.EsRoutingNodeClient.createEsClient(EsRoutingNodeClient.java:30)
at examples.EsRoutingNodeClient.<init>(EsRoutingNodeClient.java:46)
at examples.EsRoutingNodeClient.main(EsRoutingNodeClient.java:51)
194 errors
at org.elasticsearch.common.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:360)
at org.elasticsearch.common.inject.InjectorBuilder.injectDynamically(InjectorBuilder.java:178)
at org.elasticsearch.common.inject.InjectorBuilder.build(InjectorBuilder.java:110)
at org.elasticsearch.common.inject.Guice.createInjector(Guice.java:93)
at org.elasticsearch.common.inject.Guice.createInjector(Guice.java:70)
at org.elasticsearch.common.inject.ModulesBuilder.createInjector(ModulesBuilder.java:46)
at org.elasticsearch.node.Node.<init>(Node.java:200)
at org.elasticsearch.node.Node.<init>(Node.java:128)
at org.elasticsearch.node.NodeBuilder.build(NodeBuilder.java:145)
at org.elasticsearch.node.NodeBuilder.node(NodeBuilder.java:152)
at examples.EsRoutingNodeClient.createEsClient(EsRoutingNodeClient.java:30)
at examples.EsRoutingNodeClient.<init>(EsRoutingNodeClient.java:46)
at examples.EsRoutingNodeClient.main(EsRoutingNodeClient.java:51)
My ultimate aim is to use a routing node client in storm.
Any help would be very much appreciated.
Thanks!
While upgrading from 1.4 to 2.4 I ran into this same issue. I'm not 100% why, but for me it was something to due with specifying the unicast host. I'm running ES via the zip download with the defaults.
At first I had set the ports for Client Node (ie, the app i'm working on) to be outside the default range thinking I need to do this to avoid conflicts running 2 nodes on the same box. When I did this my client could never find the master. Turns out that the zen discovery only pings 5 local ports in its own range. Before I figured this out (by reading https://github.com/elastic/elasticsearch/blob/master/core/src/main/java/org/elasticsearch/discovery/zen/ping/unicast/UnicastZenPing.java) I added in a unicast.host to get the same issue you are having. After removing both settings my app is now connecting to my ES server.
here's my config
cluster.name=elasticsearch
node.name=local-dev
node.master=false
node.data=false
path.home=${project.build.directory}/es
path.data=${project.build.directory}/es/data
path.logs=${project.build.directory}/es/logs
network.host=127.0.0.1
discovery.zen.minimum_master_nodes=1
code
#Bean
public Node elasticSearchNode() throws Exception {
Settings settings = Settings.settingsBuilder().put(getProps()).build();
return nodeBuilder()
.settings(settings)
.client(true)
.node();
}
#Bean
public Client elasticSearchClient(Node node) throws Exception {
return node.client();
}
private Properties getProps() {
try {
String profile = getProfile();
log.info("Loading ES properties for env: {}", profile);
ClassPathResource resource = new ClassPathResource("es/es."+profile+".properties");
return PropertiesLoaderUtils.loadProperties(resource);
} catch (IOException e) {
log.error("Can not read property file");
throw new RuntimeException(e);
}
}
private String getProfile() {
return System.getProperty("env", "local");
}

Very simple step by step JBehave setup tutorial?

Though I have read many, but many articles on how to use JBehave, I can't get it to work. Here are the steps I went through so far:
Created new Java Project
Downloaded JBehave JAR file version 3.6.8 and added it to my build path libraries
Created a package called com.wmi.tutorials.bdd.stack.specs under the test source folder in my workspace
Added the JBehave JAR file to my Build path Library configuration
Created a JBehave story in the above-mentioned package (StackBehaviourStories.story)
Created a Java class in the above-mentioned package (StackBehaviourStory.java)
Created a Java class in the above-mentioned package (StackBehaviourSteps.java)
Imported the Given, Named, Then, When annotations in my Java class
Written two different scenarios in my JBehave story file
And still, I can't get it to work/run! =(
The story file:
Narrative:
In order to learn to with JBehave using Eclipse
As a junior Java developer though senior in .Net and in BDD
I want to define the behaviour of a custom stack
Scenario: I push an item onto the stack
Given I have an empty stack
When I push an item 'orange'
Then I should count 1
Scenario: I pop from the stack
Given I have an empty stack
When I push an item 'apple'
And I pop the stack
Then I should count 0
The story class
package com.wmi.tutorials.bdd.stack.specs
import org.jbehave.core.configuration.MostUsefulConfiguration;
import org.jbehave.core.junit.JUnitStory;
public class StackBehaviourStory extends JUnitStory {
#Override
public Configuration configuration() { return new MostUsefulConfiguration(); }
#Override
public InjectableStepsFactory stepsFactory() {
return new InstanceStepsFactory(configuration()
, new StackBehaviourSteps());
}
}
The steps class
package com.wmi.tutorials.bdd.stack.specs
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Named;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;
import org.jbehave.core.junit.Assert;
public class StackBehaviourSteps {
#Given("I have an empty stack")
public void givenIHaveAnEmptyStack() { stack = new CustomStack(); }
#When("I push an item $item")
public void whenIPushAnItem(#Named("item") String item) { stack.push(item); }
#Then("I should count $expected")
public void thenIShouldCount(#Named("expected") int expected) {
int actual = stack.count();
if (actual != expected)
throw new RuntimeException("expected:"+expected+";actual:"+actual);
}
}
I'm currently using Eclipse Kepler (4.3) JEE with everything I need to use JUnit, Google App Engine, and yes, JBehave is installed correctly following the Eclipse JBehave installation tutorial.
I can't get it to work. So how can I make it work correctly using Eclipse, JBehave and JUnit?
I know I'm late to the party here but I'm posting because this is the info I wish I had a week ago as it would've saved me a lot of pain. I'm very much into the idea of BDD, but am unfortunately finding JBehave's docs to be a bit of a nightmare, especially when it comes to Maven integration. Moreover a lot of the code I found both on their website and elsewhere didn't work. Through trial and error, and lots of tutorials, I was able to piece together the following. It runs both in Maven and Eclipse, has a single binding class that maps stories to step files, and is able to find story files located in src/test/resources.
here is a working pom file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.projectvalis.st1</groupId>
<artifactId>st1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>st1</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgument></compilerArgument>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${failsafe.and.surefire.version}</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-maven-plugin</artifactId>
<version>4.0.2</version>
<executions>
<execution>
<id>run-stories-as-embeddables</id>
<phase>integration-test</phase>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
<ignoreFailureInStories>false</ignoreFailureInStories>
<ignoreFailureInView>false</ignoreFailureInView>
<systemProperties>
<property>
<name>java.awt.headless</name>
<value>true</value>
</property>
</systemProperties>
</configuration>
<goals>
<goal>run-stories-as-embeddables</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-core</artifactId>
<version>4.0.2</version>
</dependency>
</dependencies>
</project>
here is a sample story file
Narrative:
In order to work with files to compress
As a guy who wants to win a bet with cameron
I want to ensure files are ingested and processed in the manner in which the
methods in the ingest class purport to process them.
Scenario: Simple test to give JBehave a test drive
Given a file, a.log
When the caller loads the file as a byte array
Then the byte array that is returned contains the correct number of bytes.
here is a sample step file
package com.projectvalis.compUtils.tests.ingest;
import java.io.File;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Named;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;
import org.jbehave.core.steps.Steps;
import org.junit.Assert;
import com.projectvalis.compUtils.util.fileIO.Ingest;
/**
* BDD tests for the ingest class
* #author funktapuss
*
*/
public class LoadByteSteps extends Steps {
private String fNameS;
private byte[] byteARR;
#Given("a file, $filename")
public void setFileName(#Named("filename") String filename) {
File file = new File(getClass().getResource("/" + filename).getFile());
fNameS = file.getPath();
}
#When("the caller loads the file as a byte array")
public void loadFile() {
byteARR = Ingest.loadFile(fNameS);
}
#Then("the byte array that is returned contains the "
+ "correct number of bytes.")
public void checkArrSize() {
File file = new File(fNameS);
Assert.assertTrue(
"loading error - "
+ "the file and the resultant byte array are different sizes!",
(long)byteARR.length == file.length());
}
}
and here is the generic runner
package com.projectvalis.compUtils.tests.runner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jbehave.core.configuration.Configuration;
import org.jbehave.core.configuration.MostUsefulConfiguration;
import org.jbehave.core.io.CodeLocations;
import org.jbehave.core.io.LoadFromClasspath;
import org.jbehave.core.io.StoryFinder;
import org.jbehave.core.junit.JUnitStories;
import org.jbehave.core.reporters.Format;
import org.jbehave.core.reporters.StoryReporterBuilder;
import org.jbehave.core.steps.InjectableStepsFactory;
import org.jbehave.core.steps.InstanceStepsFactory;
import org.jbehave.core.steps.Steps;
import com.projectvalis.compUtils.tests.ingest.LoadByteSteps;
/**
* generic binder for all JBehave tests. Binds all the story files to the
* step files. works for both Eclipse and Maven command line build.
* #author funktapuss
*
*/
public class JBehaveRunner_Test extends JUnitStories {
#Override
public Configuration configuration() {
return new MostUsefulConfiguration()
.useStoryLoader(
new LoadFromClasspath(this.getClass().getClassLoader()))
.useStoryReporterBuilder(
new StoryReporterBuilder()
.withDefaultFormats()
.withFormats(Format.HTML, Format.CONSOLE)
.withRelativeDirectory("jbehave-report")
);
}
#Override
public InjectableStepsFactory stepsFactory() {
ArrayList<Steps> stepFileList = new ArrayList<Steps>();
stepFileList.add(new LoadByteSteps());
return new InstanceStepsFactory(configuration(), stepFileList);
}
#Override
protected List<String> storyPaths() {
return new StoryFinder().
findPaths(CodeLocations.codeLocationFromClass(
this.getClass()),
Arrays.asList("**/*.story"),
Arrays.asList(""));
}
}
the runner lives in src/test/java//tests.runner.
the ingest test lives in src/test/java//tests.ingest.
the story files live in src/test/resources/stories.
As far as I can tell, JBehave has LOTS of options, so this certainly isn't the only way of doing things. Treat this like a template that will get you up and running quickly.
full source is on github.
Following step by step closely the jbehave Getting Started tutorial, the Run story section says: [...] the ICanToggleACell.java class will allow itself to run as a JUnit test.
This means that the JUnit library is required in your Build path.
Using Eclipse:
Select your current project and right-click it, Build path, Configure Build Path...
Properties for [current project], Java Build Path, Libraries, click [Add Library...]
Add Library, select JUnit, click [Next]
JUnit Library, JUnit library version, select the version you wish to use, click [Finish]
Java Build Path, click [OK]
Project Explorer, select your ICanToggleACell.java class, right-click it, then Run As, and click on JUnit Test
So this is the same here as for the above-example code. The StackBehaviourStory.java class should let itself run as a JUnit test after you add the proper library to the Java build path.
In my case, I have extended my Steps class from Steps (from jbehave core)
i had updated the JunitStory to JunitStories and it worked
public class StackBehaviourStory extends JUnitStory ---> JunitStories

Categories

Resources