I'm following this tutorial to learn how to connect to MongoDB in Java, however, I'm encountering a problem and despite research, I can't seem to fix it.
I do exactly what the tutorial tells me to do:
Create a new Java project
Add mongo-java-driver (I made sure I used the right one including the bson file, which seemed to be the problem in the other questions).
I create a new class and create a new MongoClient
This is my code up until now:
import com.mongodb.MongoClient;
import com.mongodb.DB;
public class MongoDemo {
public static void main(String[] args) {
MongoClient mongoClient = new MongoClient("localhost", 27017);
DB db = mongoClient.getDB("test");
}
}
Now, I think the problem is with how I added the mongo-java-driver, since I get the following error in the first line: The import com.mongodb.MongoClient cannot be resolved but I can't seem to figure out how to fix that.
I did download the correct file and added it as an external library. When I type import com.mongodb. I do get a few suggestions, however, MongoClient is not one of them. What did I do wrong?
You may be looking for something like this.
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;
public class MongoDemo {
public static void main(String[] args) {
ServerAddress serverAddress = new ServerAddress("http://localhost", 27017);
MongoClient mongoClient = new MongoClient(serverAddress);
DB db = mongoClient.getDB("test");
}
}
When creating this, I created a maven project to manage the dependencies better and included the most recent MongoDB dependencies. Here's my POM.xml
<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>MongoDBExample</groupId>
<artifactId>MongoDBExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.7.0</version>
</dependency>
</dependencies>
</project>
I haven't tested this, however, notice how some of the code has changed. This is because some of the code used in the demo has been deprecated. This should be close.
In addition to the Dale's answer:
this kind of error may occur due to incorrect addition of driver versions in POM. I recommend you to check properly POM file and try to change versions of mongodb java driver.
Also be attentive and careful with the connection of older and newer drivers, because there is the difference of syntax.
To connect to a standalone MongoDB instance (older drivers like 3.4):
MongoClient mongoClient = new MongoClient();
To connect to a standalone MongoDB instance (newer drivers like 3.8):
MongoClient mongoClient = MongoClients.create()
This difference may not be as noticeable, but adds further problems.
It should work with this code:
ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017");
MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(connectionString).build();
MongoClient mongoClient = MongoClients.create(settings);
MongoDatabase db = mongoClient.getDatabase("test");
The implementation of MongoClient is import com.mongodb.client.MongoClient;
The maven dependency is that one:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.2.3</version>
</dependency>
Related
I am trying to integrate a simple Spring Boot Application with New Relic using Micrometer.
Here are the configurations details:-
application.properties
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
management.metrics.export.newrelic.enabled=true
management.metrics.export.newrelic.api-key:MY_API_KEY // Have added the API key here
management.metrics.export.newrelic.account-id: MY_ACCOUNT_ID // Have added the account id here
logging.level.io.micrometer.newrelic=TRACE
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>springboot.micrometer.demo</groupId>
<artifactId>micrometer-new-relic</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>micrometer-new-relic</name>
<description>Demo project for actuator integration with new relic using micrometer</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-new-relic</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
I was able to integrate Prometheus with this application using micrometer-registry-prometheus dependency. I had set up Prometheus to run in a Docker container in my local system. I used the following set of commands-
docker pull prom/prometheus
docker run -p 9090:9090 -v D:/Workspaces/STS/server_sent_events_blog/micrometer-new-relic/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
prometheus.yml
global:
scrape_interval: 4s
evaluation_interval: 4s
scrape_configs:
- job_name: 'spring_micrometer'
metrics_path: '/actuator/prometheus'
scrape_interval: 5s
static_configs:
- targets: ['my_ip_address:8080']
When I navigated to localhost:9090/targets I can see that Prometheus dashboard shows my application details and that it can scrape data from it. And in the dashboard, I can see my custom metrics as well along with other metrics.
So my question is I want to achieve the same thing using New Relic. I have added the micrometer-registry-new-relic pom dependency. I have shared the application.properties file as well. I can see logs in my console saying it is sending data to New Relic-
2021-10-24 12:42:04.889 DEBUG 2672 --- [trics-publisher] i.m.n.NewRelicInsightsApiClientProvider : successfully sent 58 metrics to New Relic.
Questions:
What are the next steps?
Do I need a local running server of New Relic as I did for Prometheus?
Where can I visualize this data? I have an account in New Relic, I see nothing there
https://discuss.newrelic.com/t/integrate-spring-boot-actuator-with-new-relic/126732
As per the above link, Spring Bootctuator pushes metric as an event type “SpringBootSample”.
With NRQL query we can confirm this-
FROM SpringBootSample SELECT max(value) TIMESERIES 1 minute WHERE metricName = 'jvmMemoryCommitted'
What does the result of this query indicate? Is it a metric related to my application?
Here is the GitHub link to the demo that I have shared here.
I did not find any clear instructions on this, there are some examples out there but that uses Java agent.
Any kind of help will be highly appreciated.
From what I have learned so far.
There are 3 ways to integrate New Relic with a Spring Boot Application-
Using the Java Agent provided by New Relic
Using New Relic's Micrometer Dependency
Micormeter's New Relic Dependency
1. Configuration using Java Agent Provided By New Relic
Download the Java Agent from this URL- https://docs.newrelic.com/docs/release-notes/agent-release-notes/java-release-notes/
Extract it.
Modify the newrelic.yml file inside the extracted folder to inlcude your
license_key:
app_name:
Create a SpringBoot application with some REST endpoints.
Build the application.
Navigate to the root path where you have extracted the newrelic java agent.
Enter this command
java -javagent:<path to your new relic jar>\newrelic.jar -jar <path to your application jar>\<you rapplication jar name>.jar
To view the application metrics-
Log in to your New Relic account.
Go to Explorer Tab.
Click on Services-APM
You can see the name of your application(which you had mentioned in the newrelic.yml file) listed there.
Click on the application name.
The dashboard should look something like this.
Using New Relic's Micrometer Dependency is the preferred way to do it.
2. Configuration using New Relic's Micrometer Dependency
Add this dependency
<dependency>
<groupId>com.newrelic.telemetry</groupId>
<artifactId>micrometer-registry-new-relic</artifactId>
<version>0.7.0</version>
</dependency>
Modify the MicrometerConfig.java class to add your API Key and Application name.
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.newrelic.telemetry.Attributes;
import com.newrelic.telemetry.micrometer.NewRelicRegistry;
import com.newrelic.telemetry.micrometer.NewRelicRegistryConfig;
import java.time.Duration;
import io.micrometer.core.instrument.config.MeterFilter;
import io.micrometer.core.instrument.util.NamedThreadFactory;
#Configuration
#AutoConfigureBefore({ CompositeMeterRegistryAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class })
#AutoConfigureAfter(MetricsAutoConfiguration.class)
#ConditionalOnClass(NewRelicRegistry.class)
public class MicrometerConfig {
#Bean
public NewRelicRegistryConfig newRelicConfig() {
return new NewRelicRegistryConfig() {
#Override
public String get(String key) {
return null;
}
#Override
public String apiKey() {
return "your_api_key"; // for production purposes take it from config file
}
#Override
public Duration step() {
return Duration.ofSeconds(5);
}
#Override
public String serviceName() {
return "your_service_name"; // take it from config file
}
};
}
#Bean
public NewRelicRegistry newRelicMeterRegistry(NewRelicRegistryConfig config) throws UnknownHostException {
NewRelicRegistry newRelicRegistry = NewRelicRegistry.builder(config)
.commonAttributes(new Attributes().put("host", InetAddress.getLocalHost().getHostName())).build();
newRelicRegistry.config().meterFilter(MeterFilter.ignoreTags("plz_ignore_me"));
newRelicRegistry.config().meterFilter(MeterFilter.denyNameStartsWith("jvm.threads"));
newRelicRegistry.start(new NamedThreadFactory("newrelic.micrometer.registry"));
return newRelicRegistry;
}
}
Run the application.
To view the Application metrics-
Log in to your New Relic account.
Go to Explorer Tab.
Click on Services-OpenTelemetry
You can see the name of your application(which you had mentioned in the MicrometerConfig file) listed there.
Click on the application name.
The dashboard should look something like this.
What are the next steps?
It seems you are done and successfully shipped metrics to NewRelic.
Do I need a local running server of New Relic as I did for Prometheus?
No, NewRelic is a SaaS offering.
Where can I visualize this data? I have an account in New Relic, I see nothing there
It seems you already found it (screenshot).
What does the result of this query indicate? Is it a metric related to my application?
From the screenshot, I can't tell if it is your application but this seems to be the jvm.memory.committed metric pushed by a Spring Boot app (so likely).
In order to see if this is your app or not, you can add common tags which can tell the name of the app and some kind of an instance ID (or hostname?) in case you have multiple instances from the same app, see:
Spring Boot Docs (I would do this)
Micrometer Docs (do this if you don't use Spring Boot or want to do something tricky)
Real-World Example
This question already has answers here:
Whats the best way to bundle the whole project in Maven?
(3 answers)
Closed 4 years ago.
I have a JAVA SE project that works fine. The problem arises when I try to use it externally as a jar.
I'm using Eclipse Oxygen. My JAVA SE project, as you can see in my pom, uses JDBC4.2. Oracle doc states:
"In previous versions of JDBC, to obtain a connection, you first had
to initialize your JDBC driver by calling the method Class.forName."
Moreover:
Any JDBC 4.0 drivers that are found in your class path are
automatically loaded. (However, you must manually load any drivers
prior to JDBC 4.0 with the method Class.forName.)
For this reason, I do not need to write Class.forname(...) in DBConnection class (see below).
When I use DBConnection in my project, it works properly, but, if I create a jar and try to import it in another project, I get the following exception: "No suitable driver found for jdbc:postgresql://host:port/dbName". The following are the steps I do to create the jar:
mvn clean install
create new java project (TestProject) in a new empty clean workspace
create a test class with main
call a class that uses DBConnection from main
I have no compilation problem (all the classes from the jar are loaded correctly)
When I run the main, "getConnection" of my DBConnection class throws the following exception: "No suitable driver found for jdbc:postgresql://host:port/dbName"
If I right click on TestProject-> configure -> convert to maven project, then add postgres driver dependency, it all works fine!!!.
Shouldn't the PostgreSQL driver already be present in my jar? Why should I add it in the dependencies of the user project?
The following is the code of the class DBConnection:
package generic.util;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class DBConnection {
private static final String FILE_NAME = "db";
private static final String URL = "url";
private static final String USER = "user";
private static final String PASSWORD = "password";
private static Connection conn;
private DBConnection(){
}
public static synchronized Connection getConnection() throws SQLException, ClassNotFoundException, IOException {
if(DBConnection.conn == null || DBConnection.conn.isClosed()){
Properties props = PropertiesReader.readPropertyFile(FILE_NAME);
String url = props.getProperty(URL);
String user = props.getProperty(USER);
String password = props.getProperty(PASSWORD);
Connection conn = DriverManager.getConnection(url, user, password);
DBConnection.conn = conn;
}
return DBConnection.conn;
}
}
The following is my pom:
<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>groupid</groupId>
<artifactId>artifactid</artifactId>
<version>1.0</version>
<properties>
<skipTests>true</skipTests>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<skipTests>${skipTests}</skipTests>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.2</version>
</dependency>
</dependencies>
</project>
The default behaviour does not repackage dependend libraries into the created artifacts. Usually external libraries will not changed as often as your software does, and will be deployed to an application server.
With microservices e.g. spring-boot this has changed and you can deploy a single .jar file including all dependencies (even tomcat is included).
You have two options:
Put all libraries in a lib-folder and add it to the classpath.
Create a fat jar
I am experiencing some problems using Spring Boot and MongoDB external driver. I can't use the project Spring Data MongoDB, because I need to use the ufficial async driver given by Mongo. However, I need to use Spring Boot, because the module I am developing is part of a bigger project using this library.
Here is my pom.xml file.
<?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>
<artifactId>tx-view</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- omissis -->
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-async</artifactId>
<version>${mongodb.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
In detail, I am using Spring Boot 1.4.1 and Mongo Async Driver 3.2.2.
Here is my application.
#SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
public class TxViewApplication {
public static void main(String[] args) {
SpringApplication.run(TxViewApplication.class, args);
}
#Value("${mongo.uri}")
private String mongoUri;
#Bean
public MongoClient mongoClient() {
return MongoClients.create(mongoUri);
}
}
It follows the only (empty) test I have at the moment.
#SpringBootTest
#RunWith(SpringRunner.class)
public class ApplicationTest {
#Test
public void loadContext() throws Exception {}
}
I have no other code in this project. When I run the test, I have the following error:
2016-11-22 15:43:58.597 INFO 4572 --- [null'}-db:27017] org.mongodb.driver.cluster : Exception in monitor thread while connecting to server db:27017
com.mongodb.MongoException: java.io.IOException: Il computer remoto ha rifiutato la connessione di rete.
at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:125) ~[mongodb-driver-core-3.2.2.jar:na]
at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:128) ~[mongodb-driver-core-3.2.2.jar:na]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_101]
Caused by: java.io.IOException: Il computer remoto ha rifiutato la connessione di rete.
at sun.nio.ch.Iocp.translateErrorToIOException(Iocp.java:309) ~[na:1.8.0_101]
at sun.nio.ch.Iocp.access$700(Iocp.java:46) ~[na:1.8.0_101]
at sun.nio.ch.Iocp$EventHandlerTask.run(Iocp.java:399) ~[na:1.8.0_101]
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112) ~[na:1.8.0_101]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_101]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_101]
... 1 common frames omitted
As you can see, I have properly inserted the exclude clause in the SpringBootApplication annotation in order to stop Spring Boot to try handle its own the connection to Mongo, as suggested in Mongo tries to connect automatically to port 27017(localhost).
I have also noticed that I started to have the error after the addition to the pom.xml of the dependency to spring-boot-starter-web.
How can I inhibit Spring Boot to try to connect automatically to Mongo at startup? The same problem is present with the synchronous version of MongoDB driver.
--- EDIT ---
I have also try to build a wrapper around the async.MongoClient object, in this way:
public class MongoWrapper {
private final MongoClient mongo;
public MongoWrapper() {
mongo = MongoClients.create();
}
public MongoClient getMongo() {
return mongo;
}
}
The configuration was changed accordingly.
#Bean
public MongoWrapper mongo() {
return new MongoWrapper();
}
Unfortunately, nothing had changed. Spring Boot seems to intercept the MongoClient object also in this way :(
Thanks a lot.
You have a MongoClient bean in your own configuration which does not make any sense to me if you've excluded the auto-configuration.
I've commented out the #Bean definition in your own config and no attempt to connect to Mongo is performed now. I am not sure I answer to your question and you're probably looking for something else but if you don't want to use mongo, don't define a MongoClient in your own config!
This helped us to disable async java driver of MongoDB to use default configuration:
#EnableAutoConfiguration(exclude = {MongoReactiveAutoConfiguration.class})
I am having some issues connecting to the JCR repository within AEM 6.0. When I get to the point of creating a session on the repostory I get a javax.jcr.lock.LockException: Precondition Failed.
I have been using this tutorial to get started.
Here is my very simple code sample:
import java.io.FileNotFoundException;
import java.io.FileReader;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import org.apache.jackrabbit.commons.JcrUtils;
import com.opencsv.CSVReader;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
Repository repository;
FileReader fileReader;
CSVReader csvReader;
try {
System.out.println("connecting to repository");
repository = JcrUtils.getRepository("http://localhost:4502/crx/server");
Session session = repository.login( new SimpleCredentials("admin", "admin".toCharArray())); // throws javax.jcr.lock.LockException: Precondition Failed
}
catch(Exception e) {
System.out.println(e);
}
}
}
Any guidance would be greatly appreciated.
Inside a JCR repository, content is organized into one or more workspaces, each of which holds of a hierarchical structure of nodes and properties. So to create a jcr session & access node and properties you have to pass workspace with credentials, Default AEM workspace is crx.default
Instead of :
Session session = repository.login( new SimpleCredentials("admin", "admin".toCharArray()));
Use :
Session session = repository.login( new SimpleCredentials("admin", "admin".toCharArray()),"crx.default");
Please check the below link
javax.jcr.lock.LockException:Precondition Failed
The Obvious first: Is the AEM server running?
Secondly: Maybe your build environment is not set up correctly
I was able to set up a working project using your code and this maven file:
<?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>org.stackoverflow.test</groupId>
<artifactId>access_crx_from_outside</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>javax.jcr</groupId>
<artifactId>jcr</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-commons</artifactId>
<version>2.7.4</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr2dav</artifactId>
<version>2.6.0</version>
</dependency>
</dependencies>
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