I 'm looking for a solution to my problem a long time , I do not find anything to help me, i need to create exe from my app, when I compile it works , however when I try to generate the exe it give me a exception:
Caused by: java.lang.IllegalStateException: Location is not set.
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.load(Unknown Source)
at br.nivelamento.MainApp.initRootLayout(Unknown Source)
at br.nivelamento.MainApp.start(Unknown Source)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$163
(Unknown Source)
build.xml
<project name="Nivelamento" default="do-deploy" basedir="." xmlns:fx="javafx:com.sun.javafx.tools.ant">
<target name="init-fx-tasks">
<path id="fxant">
<filelist>
<file name="${java.home}\..\lib\ant-javafx.jar" />
<file name="${java.home}\lib\jfxrt.jar" />
</filelist>
</path>
<taskdef resource="com/sun/javafx/tools/ant/antlib.xml" uri="javafx:com.sun.javafx.tools.ant" classpathref="fxant" />
</target>
<fx:resources id="appRes">
<fx:fileset dir="dist" includes="Nivelamento.jar" />
<fx:fileset dir="dist" includes="libs/*" />
</fx:resources>
MainApp.class
package br.nivelamento;
public class MainApp extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("NivelamentoApp");
setUserAgentStylesheet(STYLESHEET_CASPIAN);
initRootLayout();
}
public static void main(String[] args){
MainApp.launch(MainApp.class, args);
}
public void initRootLayout() {
try {
// Carrega o root layout do arquivo fxml.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
// Mostra a scene (cena) contendo o root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
// Dá ao controller o acesso ao main app.
RootLayoutController controller = loader.getController();
controller.setMainApp(this);
//liga o hibernate
JpaUtil.getEntityManager();
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
Folders Tree
can anyone help me?
thanks
after many attempts I finally succeeded, the error was in
loader.setLocation (MainApp.class.getResource ("view / RootLayout.fxml"));
RootLayout.fxml see that is not the real name real name is rootLayout.fxml repairing the uppercase character was solved my problem
Related
I'm trying to run spock tests against a neo4j container using the TestContainers library. Previously, I used the test-harness library to run tests against an embedded neo4j database but the need to migrate to using TestContainers has come up. With test-harness I used a configuration file to include some necessary beans for callback functionality. Without these beans, some unit tests are failing.
Previous test-harness method
#ContextConfiguration(classes = [
Neo4jTestHarnessAutoConfiguration,
Neo4jDriverAutoConfiguration,
Neo4jDataAutoConfiguration,
CustomNeo4jConfiguration
])
#ImportAutoConfiguration(classes = [
Neo4jTestHarnessAutoConfiguration,
Neo4jDriverAutoConfiguration,
Neo4jDataAutoConfiguration
])
#Transactional
trait EmbeddedNeo4j {
// Neo4j embedded database is created in Neo4jTestHarnessAutoConfiguration
}
CustomNeo4jConfiguration
#Configuration
#EntityScan(value = {
"data.neo4j.nodes",
"data.neo4j.relationships",
"data.neo4j.queryresults"
})
#EnableNeo4jRepositories("data.neo4j.repository")
#EnableNeo4jAuditing(auditorAwareRef = "auditorAware")
public class CustomNeo4jConfiguration {
#Bean
public AuditorAware<String> auditorAware(){
return new CustomAuditorAwareImpl();
}
#Bean
public BeforeBindCallback neo4jCustomEntitiesCallback(AuditorAware<String> auditorAware) {
return new CustomNeo4jEntitiesCallback(auditorAware);
}
#Bean
public Neo4jConversions neo4jCustomConversions() {
Set<GenericConverter> additionalConverters = Collections.singleton(new InstantStringConverter());
return new Neo4jConversions(additionalConverters);
}
}
The above method works fine. All tests run properly and all beans are created.
TestContainers attempt
#Testcontainers
#Transactional
trait EmbeddedNeo4j {
#Shared
static final Neo4jContainer<?> neo4jContainer = new Neo4jContainer<>("neo4j:4.3.9")
.withReuse(true)
#DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
neo4jContainer.start()
registry.add("spring.neo4j.uri", neo4jContainer::getBoltUrl)
registry.add("spring.neo4j.authentication.username", () -> "neo4j")
registry.add("spring.neo4j.authentication.password", neo4jContainer::getAdminPassword)
}
}
With the above, all tests successfully run against the test container. However, any test that needs the functionality of the beans in the CustomNeo4jConfiguration fails.
What I've tried
I've attempted to use the same #ContextConfiguration annotations in various configurations, such as...
#ContextConfiguration(classes = [
Neo4jDriverAutoConfiguration,
Neo4jDataAutoConfiguration,
CustomNeo4jConfiguration
])
#ImportAutoConfiguration(classes = [
Neo4jDriverAutoConfiguration,
Neo4jDataAutoConfiguration
])
#Transactional
trait EmbeddedNeo4j {
TestContainer code here...
However, this fails with the following stack trace:
Failed to load ApplicationContext
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190)
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:132)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:248)
at org.spockframework.spring.SpringTestContextManager.prepareTestInstance(SpringTestContextManager.java:56)
at org.spockframework.spring.SpringInterceptor.interceptInitializerMethod(SpringInterceptor.java:43)
at org.spockframework.runtime.extension.AbstractMethodInterceptor.intercept(AbstractMethodInterceptor.java:24)
at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:101)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.spockframework.runtime.model.MethodInfo.invoke(MethodInfo.java:148)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:133)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:414)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'auditFieldRepository' defined in data.neo4j.repository.AuditFieldRepository defined in #EnableNeo4jRepositories declared on CustomNeo4jConfiguration: Cannot resolve reference to bean 'neo4jTemplate' while setting bean property 'neo4jOperations'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'neo4jTemplate' available
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:342)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:113)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1707)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1452)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:936)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:132)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
... 64 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'neo4jTemplate' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:874)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1344)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:309)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:330)
... 82 more
I've also attempted in various ways to create the missing beans, but that doesn't feel like the right path to take and that didn't produce any results.
What's the right way to use a #Configuration file with TestContainers?
Appreciate any help!
If I interpret your mixture of Java and Scala code correctly, I would recommend the following approach, but only if you insist on not using #SpringBootTest.
Also: You are using the outdated neo4j-java-driver-spring-boot-starter classes, they aren't needed for a while now in recent Spring Boot and also will potentially break SDN6+.
Please note: You should never import auto configuration classes and use them as ContextConfiguration at the same time. They are only meant to be imported via #ImportAutoConfiguration, but even that is redundant or overly complicated most of the time.
First of all, here's the pom so you get the proper dependencies:
<?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.7.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>neowithapoc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>neowithapoc</name>
<description>neowithapoc</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.17.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>neo4j</artifactId>
<version>1.17.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Solution 1
Here's a solution that goes into what you have there, with a trait - or in case of pure java - abstract test class:
package com.example.neowithapoc;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration;
import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.containers.Neo4jLabsPlugin;
#TestConfiguration
#ImportAutoConfiguration({
Neo4jAutoConfiguration.class,
Neo4jDataAutoConfiguration.class
})
#EnableTransactionManagement
#EnableNeo4jRepositories(considerNestedRepositories = true)
public abstract class EmbeddedNeo4jConfig {
static final Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:4.4")
.withLabsPlugins(Neo4jLabsPlugin.APOC)
.withReuse(true);
#DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
neo4j.start();
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
registry.add("spring.neo4j.authentication.username", () -> "neo4j");
registry.add("spring.neo4j.authentication.password", neo4j::getAdminPassword);
}
}
Use like this:
package com.example.neowithapoc;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.data.neo4j.core.Neo4jTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = EmbeddedNeo4jConfig.class)
public class SomeTest extends EmbeddedNeo4jConfig {
#Test
void whatever(#Autowired Neo4jTemplate template, #Autowired Neo4jClient client) {
assertThat(template).isNotNull();
assertThat(client).isNotNull();
String apoc = client
.query("RETURN apoc.version() AS output")
.fetchAs(String.class)
.first().get();
assertThat(apoc).startsWith("4.4");
}
}
Solution 2
I do prefer this way simpler and less complicated approach:
package com.example.neowithapoc;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.data.neo4j.core.Neo4jTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.transaction.annotation.Transactional;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.containers.Neo4jLabsPlugin;
import org.testcontainers.junit.jupiter.Testcontainers;
#SpringBootTest
#Transactional
#Testcontainers(disabledWithoutDocker = true)
public class SomeSpringBootTest {
static final Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:4.4")
.withLabsPlugins(Neo4jLabsPlugin.APOC)
.withReuse(true);
#DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
neo4j.start();
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
registry.add("spring.neo4j.authentication.username", () -> "neo4j");
registry.add("spring.neo4j.authentication.password", neo4j::getAdminPassword);
}
#Test
void whatever(#Autowired Neo4jTemplate template, #Autowired Neo4jClient client) {
assertThat(template).isNotNull();
assertThat(client).isNotNull();
String apoc = client
.query("RETURN apoc.version() AS output")
.fetchAs(String.class)
.first().get();
assertThat(apoc).startsWith("4.4");
}
}
Bonus questions custom conversions
Given the following class:
package com.example.neowithapoc;
public class SomeObject {
private final String value;
public SomeObject(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
It is not an entity and it needs some special treatment during conversions.
It can be converted back and forth like this:
import java.util.Set;
import org.neo4j.driver.Value;
import org.neo4j.driver.Values;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
public class SomeObjectConverter implements GenericConverter {
#Override public Set<ConvertiblePair> getConvertibleTypes() {
return Set.of(
new ConvertiblePair(Value.class, SomeObject.class),
new ConvertiblePair(SomeObject.class, Value.class)
);
}
#Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (source == null) {
return Value.class.isAssignableFrom(targetType.getType()) ? Values.NULL : null;
} else if (source instanceof SomeObject someObject) {
return Values.value(someObject.getValue());
} else if (source instanceof Value value) {
return new SomeObject(value.asString());
} else
throw new IllegalArgumentException();
}
}
Configure it with a #TestConfiguration (or on your main config) like this
#TestConfiguration
static class AdditionalBeans {
#Bean
SomeObjectConverter someObjectConverter() {
return new SomeObjectConverter();
}
#Bean
Neo4jConversions neo4jConversions(SomeObjectConverter someObjectConverter) {
return new Neo4jConversions(List.of(someObjectConverter));
}
}
In both cases this class is a static nested class of either EmbeddedNeo4jConfig and SomeSpringBootTest.
In the former you normally would just declare the bean method directly, but as I tried to recreate your "trait" as much as possible in Java and I do extend that class, this is not possible. Tests must not have their own #Bean methods.
After that, test like this
#Node
static class ContainerNode {
#Id #GeneratedValue
Long id;
SomeObject someObject;
public Long getId() {
return id;
}
public SomeObject getSomeObject() {
return someObject;
}
}
#Test
void conversionsShouldWork(#Autowired Neo4jTemplate template) {
var container = template.find(ContainerNode.class)
.matching("CREATE (n:ContainerNode {someObject: 'Hello'}) RETURN n")
.one();
assertThat(container).map(ContainerNode::getSomeObject).map(SomeObject::getValue).hasValue("Hello");
}
will work just fine, also with the repository.
This test here will fail
#Test
void conversionsShouldWork(#Autowired Neo4jClient client) {
var anObject = client.query("RETURN 'whatever'").fetchAs(SomeObject.class).first();
assertThat(anObject).map(SomeObject::getValue).hasValue("whatever");
}
but the Spring Data Neo4j fixed this in 6.3.3 https://github.com/spring-projects/spring-data-neo4j/issues/2594 and you would be able to manually add it to the client like this:
#TestConfiguration
static class AdditionalBeans {
#Bean
SomeObjectConverter someObjectConverter() {
return new SomeObjectConverter();
}
#Bean
Neo4jConversions neo4jConversions(SomeObjectConverter someObjectConverter) {
return new Neo4jConversions(List.of(someObjectConverter));
}
#Bean
public Neo4jClient neo4jClient(
Driver driver,
DatabaseSelectionProvider databaseSelectionProvider,
Neo4jConversions neo4jConversions) {
return Neo4jClient.with(driver)
.withDatabaseSelectionProvider(databaseSelectionProvider)
.withNeo4jConversions(neo4jConversions)
.build();
}
}
Than this test will work just fine:
#Test
void clientConversionsShouldWork(#Autowired Neo4jClient client) {
var anObject = client.query("RETURN 'whatever'").fetchAs(SomeObject.class).first();
assertThat(anObject).map(SomeObject::getValue).hasValue("whatever");
}
I have a situation where when log.error("message", exception); is called, I want some logic to happen around sending the exception to an external tool, while still maintaining the regular logging for the line to the root appender.
As an example, here would be some code and the expected outcome:
try {
...
} catch (Exception ex) {
LOG.info("abcd");
LOG.error("failed to XYZ", ex);
}
Rough Outcome:
2019-03-05 13:00:20 INFO Main:75 - abcd
2019-03-05 13:00:20 ERROR Main:76 - failed to XYZ -
Exception: exception message
stacktrace
stacktrace
...
While that is logged, I also want the exception sent through another code path.
How can I do this? I'm a bit stuck, does anyone know any good guides for this?
I don't think you really want an Appender here. It would be simpler to write a Filter instead. For reference you can find information regarding creating extensions for log4j2 on the Extending Log4j2 page of the manual
In the example below I created a simple filter that matches when the log event has a Throwable associated with it and mismatches when there is no Throwable (i.e. the Throwable is null or the log was generated from a method call that did not include a Throwable parameter).
In the example I send all matching log events to a simple file appender to illustrate that in fact it does capture only events with a Throwable. You could modify this filter to do whatever you need. You could change it to always be NEUTRAL to every event, but when a non-null Throwable is found it then triggers some special logic to send that Throwable to your external tool. Basically you would be using the filter as more of an interceptor. I will describe that change at the end.
First, here's some basic Java code to generate some logging including a log event that has a Throwable.
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class SomeClass {
private static final Logger log = LogManager.getLogger();
public static void main(String[] args){
if(log.isDebugEnabled())
log.debug("This is some debug!");
log.info("Here's some info!");
log.error("Some error happened!");
try{
specialLogic();
}catch(RuntimeException e){
log.error("Woops, an exception was detected.", e);
}
}
public static void specialLogic(){
throw new RuntimeException("Hey an exception happened! Oh no!");
}
}
Next, here's the class I call ThrowableFilter:
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.filter.AbstractFilter;
import org.apache.logging.log4j.message.Message;
#Plugin(name = "ThrowableFilter", category = "Core", elementType = "filter", printObject = true)
public final class ThrowableFilter extends AbstractFilter {
private ThrowableFilter(Result onMatch, Result onMismatch) {
super(onMatch, onMismatch);
}
public Result filter(Logger logger, Level level, Marker marker, String msg, Object[] params) {
return onMismatch;
}
public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) {
return filter(t);
}
public Result filter(Logger logger, Level level, Marker marker, Message msg, Throwable t) {
return filter(t);
}
#Override
public Result filter(LogEvent event) {
return filter(event.getThrown());
}
private Result filter(Throwable t) {
return t != null ? onMatch : onMismatch;
}
/**
* Create a ThrowableFilter.
* #param match The action to take on a match.
* #param mismatch The action to take on a mismatch.
* #return The created ThrowableFilter.
*/
#PluginFactory
public static ThrowableFilter createFilter(#PluginAttribute(value = "onMatch", defaultString = "NEUTRAL") Result onMatch,
#PluginAttribute(value = "onMismatch", defaultString = "DENY") Result onMismatch) {
return new ThrowableFilter(onMatch, onMismatch);
}
}
Finally, here is the log4j2.xml configuration file I used to test this:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
<File name="ExceptionFile" fileName="logs/exception.log" immediateFlush="true"
append="true">
<ThrowableFilter onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout
pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</File>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console" />
<AppenderRef ref="ExceptionFile" />
</Root>
</Loggers>
</Configuration>
Running the logic in SomeClass produces the following output:
On the console:
23:23:25.931 [main] DEBUG example.SomeClass - This is some debug!
23:23:25.946 [main] INFO example.SomeClass - Here's some info!
23:23:25.946 [main] ERROR example.SomeClass - Some error happened!
23:23:25.946 [main] ERROR example.SomeClass - Woops, an exception was detected.
java.lang.RuntimeException: Hey an exception happened! Oh no!
at example.SomeClass.specialLogic(SomeClass.java:25) ~[classes/:?]
at example.SomeClass.main(SomeClass.java:18) [classes/:?]
In the logs/exception.log file:
2019-03-06 23:23:25.946 [main] ERROR example.SomeClass - Woops, an exception was detected.
java.lang.RuntimeException: Hey an exception happened! Oh no!
at example.SomeClass.specialLogic(SomeClass.java:25) ~[classes/:?]
at example.SomeClass.main(SomeClass.java:18) [classes/:?]
Now to change the filter to act more as an interceptor you could alter the following methods:
//Remove parameters from constructor as they will not be used.
private ThrowableFilter() {
super();
}
...
public Result filter(Logger logger, Level level, Marker marker, String msg, Object[] params) {
//Changed to always return NEUTRAL result
return Result.NEUTRAL;
//old logic: return onMismatch;
}
...
private Result filter(Throwable t) {
//TODO: trigger the external tool here when t != null, pass t if needed.
//Changed to always return NEUTRAL result
return Result.NEUTRAL;
//old logic: return t != null ? onMatch : onMismatch;
}
/**
* Create a ThrowableFilter.
* #return The created ThrowableFilter.
*/
#PluginFactory
public static ThrowableFilter createFilter() {
return new ThrowableFilter();
}
Then in the configuration you would remove the parameters to the filter. It would now look like this:
<ThrowableFilter/>
Hope this helps you.
I have Selenium Grid2 with a hub and two nodes.
Hub is operated by:
java -jar selenium-server-standalone-2.32.0.jar -role hub -port 4444
Nodes are operated by:
java -jar selenium-server-standalone-2.32.0.jar -role node -hub http://10.20.46.171:4444/wd/hub -port 5555
In hub console, I see both nodes up and running.
My TestNB config (testng.xml):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Full suite" parallel="classes" thread-count="4">
<parameter name="hubAddress" value="http://127.0.0.1:4444/wd/hub"></parameter>
<test verbose="2" name="Full">
<packages>
<package name="com.example.tests">
</package>
</packages>
</test>
</suite>
In com/example/tests, I have a base class TestBase and 4 other classes that extend TestBase
In TestBase.java, I have:
package com.example.tests;
import java.net.MalformedURLException;
import java.net.URL;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Parameters;
public class TestBase {
protected WebDriver driver;
#BeforeClass
#Parameters("hubAddress")
public void startDriver(String hubAddress) throws MalformedURLException {
driver = new RemoteWebDriver(new URL(hubAddress), DesiredCapabilities.Firefox());
}
#AfterClass
public void stopDriver() {
driver.quit();
driver = null;
}
}
In Test1.java, I have:
package com.example.tests;
import org.testng.annotations.Test;
#Test
public class Test1 extends TestBase {
public void test1() {
driver.get("http://www.google.com/");
}
}
In Test2.java, I have:
package com.example.tests;
import org.testng.annotations.Test;
#Test
public class Test2 extends TestBase {
public void test2() {
driver.get("http://www.facebook.com/");
}
}
In Test3.java, I have:
package com.example.tests;
import org.testng.annotations.Test;
#Test
public class Test3 extends TestBase {
public void test3() {
driver.get("http://www.yahoo.com/");
}
}
In Test4.java, I have:
package com.example.tests;
import org.testng.annotations.Test;
#Test
public class Test4 extends TestBase {
public void test4() {
driver.get("http://www.cnn.com/");
}
}
I run all this with Ant. Here is a piece of code:
<target name="run-tests" depends="build">
<testng classpathref="LoadTests.classpath">
<xmlfileset dir="." includes="testng.xml"/>
</testng>
</target>
The command line:
ant run-tests
How it works now: Test1 runs on Node1 and Test2 runs on Node2 (simultaneously). AFTER THAT, Test3 runs on Node1 and Test4 runs on Node2 (simultaneously).
Desired behavior: All four tests run simultaneously in one shot: two on one node (say, Test1, Test3) and other two on the second node (Test2, Test4).
Question: What should I change so that it works as desired?
Try using #BeforeMethod instead of #BeforeClass. I know this will create a driver per method, but I think this is the only way if the #Before*annotation* occurs within the base class.
I don't quite understand why this occuring but I have teh same set up as you except use #BeforeMethod, and all is fine when running parallel threads
I have the following in my build.xml:
<junit fork="yes" printsummary="yes" filtertrace="yes">
<classpath>...</classpath>
<test name="tests.AllTests"/>
<formatter type="plain" usefile="false"/>
</junit>
I would like the JUnit results to be reported for each test as soon as they complete, unfortunately the JUnit task only prints the test results after the whole test case has completed. The test case (AllTests) is rather large, so I have to wait quite a while for the output. Is there any way to make <junit> print individual test results immediately?
I followed dkatzel's suggestion to write my own JUnitResultFormatter. Here is the code for my JUnitFormatter:
package util;
import java.io.OutputStream;
import java.io.PrintStream;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter;
import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest;
public class SimpleTestFormatter implements JUnitResultFormatter {
private PrintStream out = System.out;
#Override
public void addError(Test test, Throwable error) {
logResult(test, "ERR");
out.println(error.getMessage());
}
#Override
public void addFailure(Test test, AssertionFailedError failure) {
logResult(test, "FAIL");
out.println(failure.getMessage());
}
#Override
public void endTest(Test test) {
logResult(test, "PASS");
}
#Override
public void startTest(Test test) { }
#Override
public void endTestSuite(JUnitTest testSuite) throws BuildException { }
#Override
public void setOutput(OutputStream out) {
this.out = new PrintStream(out);
}
#Override
public void setSystemError(String err) {
// don't echo test error output
}
#Override
public void setSystemOutput(String out) {
// don't echo test output
}
#Override
public void startTestSuite(JUnitTest testSuite) throws BuildException { }
private void logResult(Test test, String result) {
out.println("[" + result + "] " + String.valueOf(test));
out.flush();
}
}
And this is how I use it in the Ant script:
<junit fork="yes" printsummary="yes" filtertrace="yes">
<classpath>...</classpath>
<test name="tests.AllTests"/>
<formatter classname="util.SimpleTestFormatter" usefile="false"/>
</junit>
Note that the class must be compiled with ant.jar and ant-junit.jar on the classpath.
I believe the built-in JUnit formatters buffer everything until the end. You should be able to write your own formatter implementation which extends org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter so that it flushes to STDOUT immediately, but I've never done it.
You can use this blog where the author makes a custom formatter and shows both the code and how to use it in the build.xml http://shaman-sir.wikidot.com/one-liner-output-formatter
There is also a similar SO question with similar info How do I configure JUnit Ant task to only produce output on failures?
I need to run java class using ant. But when i run a class file, it throws IllegalAccessException.
this is my ant code:
<target name="test">
<java classname="A" classpath=".">
</java>
</target>
I got this exception when i run this target script.
[java] java.lang.IllegalAccessException: Class org.apache.tools.ant.taskdefs.ExecuteJava can not access a member of class A with modifiers "public static"
[java] at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:180)
This is my java program
class A
{
public static void main(String[] args)
{
System.out.println("Hello java!");
}
}
Where im going wrong?
thanks,
Srinivasan R.
your class A must be public:
public class A {
public static void main(String[] args) {
System.out.println("Hello java!");
}
}