I want to make a project with Faktor IPS which is both a model project and a product deffinition project. And I want to and a UI using Linkki. Here is my project structure:
Project structure (Stack overflow won't let me add images, I hope the link works)
In the src/main/java folder are the classes to make the linkki UI and the .model.hausrat is the package where faktor ips generated the code for the policy components.
The policy components and product components are in the faktorips-repository-toc.xml in the folder src/main/resources under rg/linkki_framework/fips/Hausrat_linkki_app/model/internal/faktorips-repository-toc.xml
And this is what it looks like:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<FaktorIps-TableOfContents productDataVersion="0.0.1" xmlversion="3.0">
<ProductComponent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.deckungen.Fahrraddiebstahl___2022__01" ipsObjectId="beispiel.Fahrraddiebstahl 2022-01" ipsObjectQualifiedName="deckungen.Fahrraddiebstahl 2022-01" kindId="beispiel.Fahrraddiebstahl" versionId="2022-01" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/deckungen/Fahrraddiebstahl 2022-01.xml"/>
<ProductComponent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratGrunddeckungstyp" ipsObjectId="beispiel.HRD-Kompakt 2022-01" ipsObjectQualifiedName="deckungen.HRD-Kompakt 2022-01" kindId="beispiel.HRD-Kompakt" versionId="2022-01" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/deckungen/HRD-Kompakt 2022-01.xml"/>
<ProductComponent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratGrunddeckungstyp" ipsObjectId="beispiel.HRD-Optimal 2022-01" ipsObjectQualifiedName="deckungen.HRD-Optimal 2022-01" kindId="beispiel.HRD-Optimal" versionId="2022-01" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/deckungen/HRD-Optimal 2022-01.xml"/>
<ProductComponent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.deckungen.Ueberspannung___2022__01" ipsObjectId="beispiel.Ueberspannung 2022-01" ipsObjectQualifiedName="deckungen.Ueberspannung 2022-01" kindId="beispiel.Ueberspannung" versionId="2022-01" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/deckungen/Ueberspannung 2022-01.xml"/>
<PolicyCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Deckung" ipsObjectId="hasurat.Deckung" ipsObjectQualifiedName="hasurat.Deckung"/>
<ProductCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Deckungstyp" ipsObjectId="hasurat.Deckungstyp" ipsObjectQualifiedName="hasurat.Deckungstyp"/>
<PolicyCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratGrunddeckung" ipsObjectId="hasurat.HausratGrunddeckung" ipsObjectQualifiedName="hasurat.HausratGrunddeckung"/>
<ProductCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratGrunddeckungstyp" ipsObjectId="hasurat.HausratGrunddeckungstyp" ipsObjectQualifiedName="hasurat.HausratGrunddeckungstyp"/>
<ProductCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratProdukt" ipsObjectId="hasurat.HausratProdukt" ipsObjectQualifiedName="hasurat.HausratProdukt"/>
<PolicyCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratVertrag" ipsObjectId="hasurat.HausratVertrag" ipsObjectQualifiedName="hasurat.HausratVertrag"/>
<PolicyCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratZusatzdekung" ipsObjectId="hasurat.HausratZusatzdekung" ipsObjectQualifiedName="hasurat.HausratZusatzdekung"/>
<ProductCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratZusatzdekungstyp" ipsObjectId="hasurat.HausratZusatzdekungstyp" ipsObjectQualifiedName="hasurat.HausratZusatzdekungstyp"/>
<ProductCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Produkt" ipsObjectId="hasurat.Produkt" ipsObjectQualifiedName="hasurat.Produkt"/>
<PolicyCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Vertrag" ipsObjectId="hasurat.Vertrag" ipsObjectQualifiedName="hasurat.Vertrag"/>
<EnumContent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Zahlweise" ipsObjectId="modell.hasurat.Zahlweise" ipsObjectQualifiedName="hasurat.Zahlweise.Type"/>
<ProductComponent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratProdukt" ipsObjectId="beispiel.HR-Kompakt 2022-01" ipsObjectQualifiedName="produkt.HR-Kompakt 2022-01" kindId="beispiel.HR-Kompakt" versionId="2022-01" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/produkt/HR-Kompakt 2022-01.xml"/>
<ProductComponent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratProdukt" ipsObjectId="beispiel.HR-Optimal 2022-01" ipsObjectQualifiedName="produkt.HR-Optimal 2022-01" kindId="beispiel.HR-Optimal" versionId="2022-01" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/produkt/HR-Optimal 2022-01.xml"/>
<TableContent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Tariftabelle" ipsObjectId="tabellen.Tariftabelle Kompakt" ipsObjectQualifiedName="tabellen.Tariftabelle Kompakt" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/tabellen/Tariftabelle Kompakt.xml"/>
<TableContent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Tariftabelle" ipsObjectId="tabellen.Tariftabelle Optimal" ipsObjectQualifiedName="tabellen.Tariftabelle Optimal" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/tabellen/Tariftabelle Optimal.xml"/>
<TableContent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Tarifzonentabelle" ipsObjectId="tabellen.Tarifzonentabelle" ipsObjectQualifiedName="tabellen.Tarifzonentabelle" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/tabellen/Tarifzonentabelle.xml"/>
</FaktorIps-TableOfContents>
At one point I try to get a list of all product components that are instances of the HausratProdukt. like this:
private final List<HausratProdukt> produkte;
private IRuntimeRepository repository;
this.repository = PolicyRuntimeRepositoryLookup.getInstance().getRuntimeRepository();
this.produkte = repository.getAllProductComponents(HausratProdukt.class);
The class PolicyRuntimeRepositoryLookup looks like this:
public class PolicyRuntimeRepositoryLookup implements IRuntimeRepositoryLookup {
private static final long serialVersionUID = 1L;
private static final PolicyRuntimeRepositoryLookup SINGLETON = new PolicyRuntimeRepositoryLookup();
private static final String TOC_PATH = "org/linkki_framework/fips/Hausrat_linkki_app/model/internal/faktorips-repository-toc.xml";
//"de/faktorzehn/ipm/core/model/internal/faktorips-repository-toc.xml";
private transient IRuntimeRepository runtimeRepository;
private PolicyRuntimeRepositoryLookup() {
runtimeRepository = ClassloaderRuntimeRepository.create(TOC_PATH);
}
public static PolicyRuntimeRepositoryLookup getInstance() {
return SINGLETON;
}
#Override
public IRuntimeRepository getRuntimeRepository() {
return runtimeRepository;
}
private Object readResolve() {
return SINGLETON;
}
}
It crashes at the line:
this.produkte = repository.getAllProductComponents(HausratProdukt.class);
With the following error:
java.lang.RuntimeException: Can't load class org.linkki_framework.fips.Hausrat_linkki_app.model.deckungen.Ueberspannung___2022__01
at org.faktorips.runtime.internal.AbstractTocBasedRuntimeRepository.getClass(AbstractTocBasedRuntimeRepository.java:272)
at org.faktorips.runtime.internal.AbstractClassLoadingRuntimeRepository.getAllProductComponentsInternal(AbstractClassLoadingRuntimeRepository.java:329)
at org.faktorips.runtime.internal.AbstractRuntimeRepository.getAllProductComponents(AbstractRuntimeRepository.java:265)
at org.linkki_framework.fips.Hausrat_linkki_app.pmo.AngebotSectionPmo.<init>(AngebotSectionPmo.java:44)
at org.linkki_framework.fips.Hausrat_linkki_app.page.AngebotPage.createContent(AngebotPage.java:37)
at org.linkki_framework.fips.Hausrat_linkki_app.view.AngebotView.enter(AngebotView.java:47)
at com.vaadin.navigator.Navigator.performNavigateTo(Navigator.java:778)
at com.vaadin.navigator.Navigator.lambda$navigateTo$9a874efd$1(Navigator.java:702)
at com.vaadin.navigator.ViewBeforeLeaveEvent.navigate(ViewBeforeLeaveEvent.java:54)
at com.vaadin.navigator.View.beforeLeave(View.java:79)
at com.vaadin.navigator.Navigator.runAfterLeaveConfirmation(Navigator.java:730)
at com.vaadin.navigator.Navigator.navigateTo(Navigator.java:701)
at com.vaadin.navigator.Navigator.navigateTo(Navigator.java:678)
at org.linkki_framework.fips.Hausrat_linkki_app.menu.AngebotMenuItem.lambda$0(AngebotMenuItem.java:27)
at com.vaadin.ui.MenuBar.changeVariables(MenuBar.java:210)
at com.vaadin.server.communication.ServerRpcHandler.changeVariables(ServerRpcHandler.java:616)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:468)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:411)
at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:275)
at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:91)
at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1637)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:464)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.ClassNotFoundException: org.linkki_framework.fips.Hausrat_linkki_app.model.deckungen.Ueberspannung___2022__01
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at org.faktorips.runtime.internal.AbstractTocBasedRuntimeRepository.getClass(AbstractTocBasedRuntimeRepository.java:269)
... 60 more
I noticed that the faktorips-repository-toc.xml saves product components with an implementationClass of whatever Policy class they are a an instance of.
For example beispiel.HRD-Kompakt 2022-1 has an implementationClass of ...hasurat.HausratGrunddeckungstyp, but those product components that are actually instances of Zusatzdeckungstyp are saved in the toc.xml file with their actual name in the implementationClass.
For example ...deckungen.Ueberspannung___2022__01 instead of ...hasurat.HausratZusatzdekungstyp, which I would actually expect.
I have no idea why it saves only these differently, or how to change it, since this is a built in component of faktor ips.
Maybe the builtin method repository.getAllProductComponents(...) searches for classes in the src/main/java folder (where all the other classes are) and doesn't find these specific ones, which are in the src/main/resources folder?
But this too is automatically generated and I don't know how to change it. Of course I could manually move the classes into the src/main/java folder, but that would kind of defeat the purpose of it being automatically generated. Can anyone help?
The reason for the specific implementation classes is that you use formulas in those products. When using formulas with Faktor-IPS, there are two options:
Generating and compiling Java code for them
Generating Java code inside their XML files and interpreting it with a Groovy formula evaluator at runtime
You can choose, which option you use in a project in the 'Faktor-IPS Code Generator Settings' (rightclick on the project -> properties -> 'Faktor-IPS Code Generator Settings' or in the XML of the .ipsproject file). The property 'Formula Compiling' can be set to 'Subclass' for the first or 'XML' for the second option. The default value 'Both' generates table-of-contents-entries and Java classes like the first option and additionally Java code in the XMLs like the second.
When using Maven for your project, you need to adapt to the variant you choose. With variant 1, you need to make sure that Java files in src/main/resources are also compiled as described in https://www.faktorzehn.org/dokumentation/verwendung-von-faktor-ips-projekten-als-maven-dependencies/ :
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals><goal>add-source</goal></goals>
<configuration>
<sources>
<source>${project.basedir}/derived</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
If you choose the second option, you need to add a dependency to https://mvnrepository.com/artifact/org.faktorips/faktorips-runtime-groovy and add the formula evaluator to your repository with
repository.setFormulaEvaluatorFactory(new GroovyFormulaEvaluatorFactory());
Related
When I output birthDate in a Thymeleaf template it prints the date/time:
1962-04-18 00:00:00.0
How can I output just the date?
This is what I've currently got:
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
Thymeleaf template:
<tbody>
<tr th:each="tempUser : ${users}">
<td th:text="${#temporals.format(tempUser.birthDate, 'yyyy-MM-dd')}" />
</tr>
</tbody>
Variable in User.java
#DateTimeFormat(pattern="yyyy-MM-dd")
#Column(name="birth_date")
private Date birthDate;
When I try to view the page I get:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Mon Oct 12 16:31:36 BST 2020
There was an unexpected error (type=Internal Server Error, status=500).
An error happened during template parsing (template: "class path resource [templates/users/list-users.html]")
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/users/list-users.html]")
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100)
at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072)
at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:362)
at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "#temporals.format(tempUser.birthDate, 'yyyy-MM-dd')" (template: "users/list-users" - line 43, col 9)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393)
at org.attoparser.MarkupParser.parse(MarkupParser.java:257)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230)
... 48 more
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "#temporals.format(tempUser.birthDate, 'yyyy-MM-dd')" (template: "users/list-users" - line 43, col 9)
at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:290)
at org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:166)
at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:66)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138)
at org.thymeleaf.standard.processor.AbstractStandardExpressionAttributeTagProcessor.doProcess(AbstractStandardExpressionAttributeTagProcessor.java:144)
at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74)
at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95)
at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633)
at org.thymeleaf.engine.ProcessorTemplateHandler.handleStandaloneElement(ProcessorTemplateHandler.java:918)
at org.thymeleaf.engine.StandaloneElementTag.beHandled(StandaloneElementTag.java:228)
at org.thymeleaf.engine.Model.process(Model.java:282)
at org.thymeleaf.engine.Model.process(Model.java:290)
at org.thymeleaf.engine.IteratedGatheringModelProcessable.processIterationModel(IteratedGatheringModelProcessable.java:367)
at org.thymeleaf.engine.IteratedGatheringModelProcessable.process(IteratedGatheringModelProcessable.java:221)
at org.thymeleaf.engine.ProcessorTemplateHandler.handleCloseElement(ProcessorTemplateHandler.java:1640)
at org.thymeleaf.engine.TemplateHandlerAdapterMarkupHandler.handleAutoCloseElementEnd(TemplateHandlerAdapterMarkupHandler.java:428)
at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler$InlineMarkupAdapterPreProcessorHandler.handleAutoCloseElementEnd(InlinedOutputExpressionMarkupHandler.java:344)
at org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.handleAutoCloseElementEnd(OutputExpressionInlinePreProcessorHandler.java:237)
at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler.handleAutoCloseElementEnd(InlinedOutputExpressionMarkupHandler.java:184)
at org.attoparser.HtmlElement.handleAutoCloseElementEnd(HtmlElement.java:199)
at org.attoparser.HtmlMarkupHandler.handleAutoCloseElementEnd(HtmlMarkupHandler.java:472)
at org.attoparser.MarkupEventProcessorHandler.checkStackForElement(MarkupEventProcessorHandler.java:763)
at org.attoparser.MarkupEventProcessorHandler.handleCloseElementStart(MarkupEventProcessorHandler.java:439)
at org.attoparser.ParsingElementMarkupUtil.parseCloseElement(ParsingElementMarkupUtil.java:197)
at org.attoparser.MarkupParser.parseBuffer(MarkupParser.java:725)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:301)
... 50 more
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1004E: Method call: Method format(java.sql.Timestamp,java.lang.String) cannot be found on type org.thymeleaf.extras.java8time.expression.Temporals
at org.springframework.expression.spel.ast.MethodReference.findAccessorForMethod(MethodReference.java:226)
at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:135)
at org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:55)
at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:387)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:92)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:112)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:337)
at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:263)
... 76 more
<p th:text="${#temporals.format(localDate, 'dd-MM-yyyy')}"></p>
The above code gives the following output:
12-10-2020
And of course, you must have the following dependencies added, in the pom.xml file.
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
The latest versions of thymeleaf and thymeleaf-spring5 can be found on Maven Central. Note that, for a Spring 4 project, the thymeleaf-spring4 library must be used instead of thymeleaf-spring5.
Moreover, in order to work with Java 8 Date classes, we will add the following dependency to the pom.xml:
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
The thymeleaf extras is an optional module, that was created for compatibility with the Java 8 Time API. It adds a #temporals object to the Context as a utility object processor during expression evaluations. This means that it can be used to evaluate expressions in Object-Graph Navigation Language (OGNL) and Spring Expression Language (SpringEL).
The Time package is a date, time, and calendar API for the Java SE platform. The main difference between old legacy Date and is that the new API distinguishes between machine and human views of a timeline. The machine view reveals a sequence of integral values relative to the epoch, whereas view reveals a set of fields (e.g., year or day).
To work with the Time package, configure the template engine to use the Java8TimeDialect:
private ISpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.addDialect(new Java8TimeDialect());
engine.setTemplateResolver(templateResolver);
return engine;
}
This will add the #temporals object similar to the ones in the Standard Dialect, allowing the formatting and creation of Temporal objects from Thymeleaf templates.
In order to test the processing of new and old classes, create the following variables and add them as model objects to the controller class:
model.addAttribute("standardDate", new Date());
model.addAttribute("localDateTime", LocalDateTime.now());
model.addAttribute("localDate", LocalDate.now());
model.addAttribute("timestamp", Instant.now());
I've defined my Gemfire's "client-cache.xml" as below:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gfe="http://www.springframework.org/schema/gemfire"
xsi:schemaLocation="http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<gfe:pool id="client" subscription-enabled="true">
<gfe:locator host="localhost" port="41114"/>
</gfe:pool>
<gfe:client-cache pool-name="client"/>
<gfe:client-region id="dataRegion" name="dataRegion" pool-name="client" shortcut="PROXY"/>
</beans>
I want to create a corresponding Java Configuration for the same.
I've tried below configuration:
#Resource
private Cache gemfireCache;
#Resource
private Pool client;
#Bean
public PoolFactoryBean client() {
PoolFactoryBean client = new PoolFactoryBean();
client.setSubscriptionEnabled(true);
client.addLocators(new ConnectionEndpoint("localhost", 41114));
return client;
}
#Bean
public ClientRegionFactoryBean<String, AbstractContent> dataRegion() {
ClientRegionFactoryBean<String, AbstractContent> dataRegionFactory = new ClientRegionFactoryBean<>();
dataRegionFactory.setPoolName("client");
dataRegionFactory.setName("dataRegion");
dataRegionFactory.setShortcut(ClientRegionShortcut.PROXY);
return dataRegionFactory;
}
#Bean
public ClientCacheFactoryBean gemfireCache() {
ClientCacheFactoryBean clientCacheFactory = new ClientCacheFactoryBean();
clientCacheFactory.setPoolName("client");
clientCacheFactory.setPdxSerializer(mappingPdxSerializer());
return clientCacheFactory;
}
#Bean
public PlatformTransactionManager gemfireTransactionManager() throws Exception {
return new GemfireTransactionManager(gemfireCache);
}
However, I keep running into exception saying :
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.gemstone.gemfire.cache.client.ClientCache] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:372)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:369)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332)
at org.springframework.data.gemfire.client.PoolFactoryBean.eagerlyInitializeClientCacheIfNotPresent(PoolFactoryBean.java:218)
at org.springframework.data.gemfire.client.PoolFactoryBean.getObject(PoolFactoryBean.java:171)
at org.springframework.data.gemfire.client.PoolFactoryBean.getObject(PoolFactoryBean.java:65)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:168)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:103)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1590)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:317)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:296)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
Is it not possible to transform the above XML into Java based configuration?
Any help would be appreciated.
Thanks.
===============Edited below per John's comments==============
#John,
I tried the example mentioned # sample test case for gemfire client and the sample as it is, worked fine.
I'm using locator and the example worked fine with the locators configuration as
gemfirePool.setLocators(Collections.singletonList(new InetSocketAddress(host, port))).
However, I'm using spring-data-gemfire version 1.8.2.RELEASE as per recommendations of Pivotal support.
So, I
upgraded the spring-data-gemfire version to 1.8.2.RELEASE # pom.xml,
fixed the compilation errors
(commented gemfireCache.setLazyInitialize(true)),
and changed gemfirePool.setLocators(Collections.singletonList(new InetSocketAddress(locatorHost, locatorPort))) to gemfirePool.addLocators(Collections.singletonList(new ConnectionEndpoint(locatorHost, locatorPort))),
the test case went for a toss.
The test case started giving me below exception:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:249)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'gemfireCache' defined in io.pivotal.gemfire.cache.client.SpringGemFireClientCacheTest$SpringGemFireClientConfiguration: Unsatisfied dependency expressed through constructor argument with index 1 of type [com.gemstone.gemfire.cache.client.Pool]: : Error creating bean with name 'gemfirePool': FactoryBean threw exception on object creation; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.gemstone.gemfire.cache.client.ClientCache] is defined; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gemfirePool': FactoryBean threw exception on object creation; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.gemstone.gemfire.cache.client.ClientCache] is defined
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:464)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:753)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:125)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:261)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 25 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gemfirePool': FactoryBean threw exception on object creation; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.gemstone.gemfire.cache.client.ClientCache] is defined
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:175)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:103)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1585)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:254)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1192)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 43 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.gemstone.gemfire.cache.client.ClientCache] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:372)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332)
at org.springframework.data.gemfire.client.PoolFactoryBean.eagerlyInitializeClientCacheIfNotPresent(PoolFactoryBean.java:218)
at org.springframework.data.gemfire.client.PoolFactoryBean.getObject(PoolFactoryBean.java:171)
at org.springframework.data.gemfire.client.PoolFactoryBean.getObject(PoolFactoryBean.java:65)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:168)
... 52 more
So, it looks like, it's an issue with the spring-data-gemfire 1.8.2.RELEASE.
I'm not really sure if I should simply revert back to 1.6.2.RELEASE and, what would I lose on reverting back to a previous revision.
I created another sample spring boot application:
pom.xml
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.cdk.test
TestGemfireLocators
0.0.1-SNAPSHOT
<parent>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>2.0.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-gemfire</artifactId>
<version>1.8.2.RELEASE</version>
</dependency>
</dependencies>
Application.java
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean(name = "region")
public ClientRegionFactoryBean region(ClientCache gemfireCache, Pool gemfirePool) {
ClientRegionFactoryBean versionedRegion = new ClientRegionFactoryBean();
versionedRegion.setName("region");
versionedRegion.setCache(gemfireCache);
versionedRegion.setPool(gemfirePool);
versionedRegion.setShortcut(ClientRegionShortcut.PROXY);
return versionedRegion;
}
#Bean
public ClientCacheFactoryBean gemfireCache(#Qualifier("gemfireProperties") Properties gemfireProperties,
Pool gemfirePool) {
ClientCacheFactoryBean gemfireCache = new ClientCacheFactoryBean();
gemfireCache.setPool(gemfirePool);
gemfireCache.setProperties(gemfireProperties);
return gemfireCache;
}
#Bean(name = GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME)
public PoolFactoryBean gemfirePool(#Value("${locator.host}") String host, #Value("${locator.port}") int port) {
PoolFactoryBean gemfirePool = new PoolFactoryBean();
gemfirePool.setName(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME);
gemfirePool.setSubscriptionEnabled(true);
gemfirePool.addLocators(new ConnectionEndpoint(host, port));
return gemfirePool;
}
#Bean
public Properties gemfireProperties(#Value("${gemfire.log.level:config}") String logLevel) {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("log-level", logLevel);
return gemfireProperties;
}
}
The above code too, doesn't work and returns same exception. I tried above code with the default version of "spring-data-gemfire" contained with-in io.spring.platform (1.7.4.RELEASE) and still the same result.
-------------POST John's comments and reference program-------------------
Thanks a lot John. The sample provided by you helped me, however, I had to make a few changes to the code. Below is how my final project looks like (if you notice, I'm injecting GemfireCache instead of ClientCache):
pom.xml
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.cdk.test
TestGemfireLocators
0.0.1-SNAPSHOT
<parent>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-gemfire</artifactId>
<version>1.8.2.RELEASE</version>
</dependency>
</dependencies>
Application.java
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Resource(name = "myRegion")
private Region<String, Object> myRegion;
int intValue(Long value) {
return value.intValue();
}
String logLevel() {
return System.getProperty("gemfire.log-level", "config");
}
Properties gemfireProperties() {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("log-level", logLevel());
return gemfireProperties;
}
#Bean
ClientCacheFactoryBean gemfireCache() {
ClientCacheFactoryBean gemfireCache = new ClientCacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setProperties(gemfireProperties());
return gemfireCache;
}
#Bean(name = GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME)
PoolFactoryBean gemfirePool(#Value("${locator.host}") String host, #Value("${locator.port}") int port) {
PoolFactoryBean gemfirePool = new PoolFactoryBean();
gemfirePool.setKeepAlive(false);
gemfirePool.setSubscriptionEnabled(true);
gemfirePool.setThreadLocalConnections(false);
gemfirePool.addLocators(new ConnectionEndpoint(host, port));
return gemfirePool;
}
#Bean(name = "myRegion")
ClientRegionFactoryBean<String, Object> myRegion(#Value("${region.name}") String regionName, GemFireCache gemfireCache,
Pool gemfirePool) {
ClientRegionFactoryBean<String, Object> myRegion = new ClientRegionFactoryBean<>();
myRegion.setCache(gemfireCache);
myRegion.setName(regionName);
myRegion.setPool(gemfirePool);
myRegion.setShortcut(ClientRegionShortcut.PROXY);
return myRegion;
}
#Bean
PlatformTransactionManager gemfireTransactionManager(GemFireCache gemfireCache) {
return new GemfireTransactionManager((Cache) gemfireCache);
}
}
The NoSuchBeanDefinitionException pertains to the injected Cache reference in your application Java configuration class...
#Resource
private Cache gemfireCache
NOTE: you might prefer to use #Inject or Spring's #Autowired annotation instead, since this is technically more accurate.
The problem here is there is no Spring bean defined of type "Cache" in your Spring Java configuration.
If you look more closely at the ClientCacheFactoryBean, getObjectType() method, which Spring uses to inspect bean (definitions) during autowiring of application components "by type", you see that it returns ClientCache.class. Technically, ClientCacheFactoryBean.getObjectType() also returns the actual cache object's type, but I do not recall when Spring inspects the available bean definitions to resolve type dependencies. Plus, I think the Spring container also maintains a type-to-bean mapping (a.k.a. cache) during parsing. The only reason the later is relevant is because GemFire only has 1 implementation of Cache and ClientCache, and that implementation, namely GemFireCacheImpl implements both interfaces. So, it seemingly should be resolvable, but...
Anyway, all of this is to explain the exception with a bit more clarity.
Unfortunately, you cannot use...
return new GemfireTransactionManager(gemfireCache());
Since the gemfireCache() bean definition "method" returns an instance of the ClientCacheFactoryBean and the GemfireTransactionManager constructor expects an instance of Cache.
However, you can define arguments of type Cache, ClientCache and GemFireCache as needed by the SDG FactoryBeans. For instance, your gemfireTransactionManager bean can be defined as...
#Bean
public PlatformTransactionManager gemfireTransactionManager(GemFireCache gemfireCache) {
return new GemfireTransactionManager((Cache) gemfireCache));
}
NOTE: ClientCache extends GemFireCache.
Likewise, your Region bean definition, "dataRegion" also expects and can take an instance of the cache like so...
#Bean
public ClientRegionFactoryBean<String, AbstractContent> dataRegion(ClientCache gemfireCache, Pool gemfirePool) {
...
dataRegion.setCache(gemfireCache);
dataRegion.setPool(gemfirePool);
...
}
Also notice, I can pass a reference to the GemFire Pool that the Region should use for data access operations to the cluster servers.
Spring treats Java configuration #Bean definition method parameters as "type dependencies", so you can just defined the expected, resulting bean type required by the bean component in question (e.g. "gemfireTransactionManager" which expects a "Cache" bean dependency).
In general, there is no problem switching from XML to Java configuration. In fact, I encourage it and have even been using Java config more and more in my examples (for instance). In time I plan to convert most of the spring-gemfire-examples over to using Spring Boot and Java configuration.
Speaking of the spring-gemfire-examples, there is also an example with Java config. But, I think this example demonstrates a peer cache. So, you may find the examples in 3 more helpful since I compare and contrast both GemFire native configuration and Spring configuration using both XML and Java.
For instance, my ClientCache Java configuration example has both a GemFire Cache server Java config and client Java config.
Anyway, hope this helps and if you more questions, feel free to reach out.
Cheers,
John
Update - 2016-07-19
Example (& test) for this problem using your GemFire cache client, Spring Java configuration provided here.
Try using the bean method instead of #Resource, e.g.
return new GemfireTransactionManager(gemfireCache());
Running spring boot tests with Geode I had startup error like this (paths redacted):
Invalid bean definition with name 'gemfireCache' defined in class path resource... CacheServerConfiguration... There is already... ClientCacheConfiguration... defined in class path resource... bound
It was fixed by adding
spring.main.allow-bean-definition-overriding=true to my application.properties file
I'm developing a spring command line app which uses dependency of external jars. When I run the app from eclipse it works perfectly, but when I export it as runnable jar it fails to autowire the dependecies from the sub-package. However if I write each bean definition in spring-context, then it works. What is the problem with it? Is #Component not working or component-scan base package or something else?
Here is Spring-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:property-placeholder location="classpath*:/connection.properties, classpath*:/log4j.properties" />
<import resource="classpath*:/sm-service-context.xml" />
<context:annotation-config />
<context:component-scan base-package="com.hca.sm.migration" />
<bean class="com.hca.sm.migration.MigrationController" />
</beans>
Update: ERROR Stacktrace:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.hca.sm.migration.MigrationController#0': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: protected com.hca.sm.migration.soap.util.SOAPMessageUtil com.hca.sm.migration.MigrationController.soapMessageUtil; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.hca.sm.migration.soap.util.SOAPMessageUtil] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.hca.sm.migration.SMMigrationApp.main(SMMigrationApp.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: protected com.hca.sm.migration.soap.util.SOAPMessageUtil com.hca.sm.migration.MigrationController.soapMessageUtil; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.hca.sm.migration.soap.util.SOAPMessageUtil] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
... 18 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.hca.sm.migration.soap.util.SOAPMessageUtil] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1103)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:963)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
... 20 more
ERROR [main] (SMMigrationApp.java:17) - org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.hca.sm.migration.MigrationController#0': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: protected com.hca.sm.migration.soap.util.SOAPMessageUtil com.hca.sm.migration.MigrationController.soapMessageUtil; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.hca.sm.migration.soap.util.SOAPMessageUtil] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
MigrationController.java:
package com.hca.sm.migration;
import java.util.List;
import javax.annotation.PostConstruct;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/* other imports */
#Component
public class MigrationController extends AbstractEntityUtil {
private static final Logger logger = Logger.getLogger(MigrationController.class.getName());
#Autowired
protected SOAPMessageUtil soapMessageUtil;
#Autowired
protected SOAPGroupUtil soapGroupUtil;
#Autowired
protected SOAPMessageThreadUtil soapMessageThreadUtil;
#Autowired
protected RestServiceUtil restServiceUtil;
private SecureMail connectionPort = null;
private GroupList groupList = null;
#PostConstruct
public void init() {
connectionPort = soapConnectionUtil.getSOAPConnection();
}
public void migrateOldSmToNew(String clientId, String dryRun) {
groupList = soapGroupUtil.getListOfGroupsByClientId(clientId, connectionPort) ;
/* other logic*/
}
}
And my main class from where I call the controller:
package com.hca.sm.migration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
#Component
public final class SMMigrationApp {
public static void main(String[] args) {
String clientId = "dc=ihcs,dc=com";
String dryRun = "true";
try {
ApplicationContext smApplicationContext = new ClassPathXmlApplicationContext("classpath*:/SM-MigrationApplicationContext.xml");
// migration
MigrationController migrationController = (MigrationController) smApplicationContext.getBean(MigrationController.class.getName()); //here is error
migrationController.migrateOldSmToNew(clientId, dryRun);
} catch (Exception e) {
e.printStackTrace();
}
}
}
OKAY! So after much of digging I chose another approach to pack my application as runnable jar and it seams to work for me. However I still don't get why the component-scan-base package was is not working in this case. I assume it has to do something with the way maven assemble the jar and .classpath inside menifest.mf. So I suggest if anyone is having such problem use following plugin:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.2.2.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
This is the most simple way to create standalone runnable jar which includes all the dependencies.
To compile and package run maven command at console:
mvn clean package
To run the jar at console :
java -jar jarName.jar
Hope this helps someone like me!!!!
I am trying to write a JavaFx8 application using Maven. I wrote a simple application main class and a fxml file (a root fxml file that does nothing).
When I try to load the fxml root file I have the error "Location is not set":
Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:363)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:303)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:875)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$147(LauncherImpl.java:157)
at com.sun.javafx.application.LauncherImpl$$Lambda$53/99550389.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Location is not set.
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2428)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2403)
at org.aklal.todofx.tasks.App.initRootLayout(App.java:58)
at org.aklal.todofx.tasks.App.start(App.java:31)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$153(LauncherImpl.java:821)
at com.sun.javafx.application.LauncherImpl$$Lambda$56/1712616138.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$166(PlatformImpl.java:323)
at com.sun.javafx.application.PlatformImpl$$Lambda$49/1268447657.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$164(PlatformImpl.java:292)
at com.sun.javafx.application.PlatformImpl$$Lambda$52/511893999.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$165(PlatformImpl.java:291)
at com.sun.javafx.application.PlatformImpl$$Lambda$50/1851691492.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$45(GtkApplication.java:126)
at com.sun.glass.ui.gtk.GtkApplication$$Lambda$42/584634336.run(Unknown Source)
... 1 more
Exception running application org.aklal.todofx.tasks.App
I am not new to JavaFx8 and I already had this kind of error but this time I do not find the problem.
My classes are:
App.java
package org.aklal.todofx.tasks;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class App extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
public App() {
System.out.println("TEST");
}
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("TEST App (JavaFx with Maven)");
initRootLayout();
}
public void initRootLayout() {
try {
//to check classpaths
Unused un = new Unused();
System.out.println("TESTAPP\n\t" + this.getClass());
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(App.class.getResource("view/RootLayout.fxml"));
//loader.setLocation(App.class.getResource("TestRootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public Stage getPrimaryStage() {
return primaryStage;
}
public static void main(String[] args) {
launch(args);
}
}
RootLayout.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane prefHeight="500.0" prefWidth="1024.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
<!-- TODO Add Nodes -->
</BorderPane>
I checked the classpathes printing out the getClass output (Is that the correct way to have classpath?), to do so I wrote an "Unused.java" class in the fxml file package:
package org.aklal.todofx.tasks.view;
public class Unused {
public Unused(){
System.out.println("Unused\n\t" + this.getClass());
}
}
When I run the App, the getClass ouputs are:
Unused
class org.aklal.todofx.tasks.view
Unused APP
class org.aklal.todofx.tasks.App
So in my opinion the path ("view/RootLayout.fxml") I give to loader.setLocation is correct, isn't it?.
I also tried to put the root fxml file (renamed TestRootLayout) in the main class' package, I still have the error.
Can anybody see an error?
Note
I already wrote JavaFx apps but I never used Maven to do it, the purpose of this project is to set a JavaFx8 project with Maven. I think my problem does not come from Maven but I give you the commands I done to set my project, maybe there is something wrong:
I did the command:
mvn archetype:generate -DgroupId=org.aklal -DartifactId=javafx-with-maven -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
I modified the pom.xml 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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.aklal</groupId>
<artifactId>javafx-with-maven</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>javafx-with-maven</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>JavaFXSimpleApp</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>com.zenjava</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>2.0</version>
<configuration>
<mainClass>org.aklal.todofx.tasks.App</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
and then:
mvn eclipse:eclipse
and in Eclipse: Import -> Existing Projects into workspace
fxrt.jar is included in JRE System Library
Update:
To check if the problem has not a more general reason, I wrote the main class with hard coded elements:
public class App extends Application {
public static void main(String args[]) {
launch(args);
}
#Override
public void start(Stage stage) {
Button bouton = new Button("Click");
bouton.setOnAction(e -> System.out.println("Clicked!"));
StackPane root = new StackPane();
root.getChildren().add(bouton);
stage.setScene(new Scene(root));
stage.setWidth(300);
stage.setHeight(300);
stage.setTitle("JavaFx8 with Maven");
stage.show();
}
}
It works, so I guess everything is in order. The question remains: why does the setLocation not work?
Update:
There is definitely a problem with the path to the fxml file. If I change:
FXMLLoader loader = new FXMLLoader();
loader.setLocation(App.class.getResource("view/RootLayout.fxml"));
with:
String pathToFxml = "absolute_path/RootLayout.fxml";
URL fxmlUrl = new File(pathToFxml).toURI().toURL();
loader.setLocation(fxmlUrl);
then it works
for now the jar I created did not have fxml files. I guess I made a
mistake, I will give one more try and let you know
You need to add the FXML file in a sub-directory of src/main/resources not src/main/java
If you call App.class.getResource("view/RootLayout.fxml") then the FXML file has to be in the directory: src/main/resources/mypackage/view where mypackage is the package of the class App.
If you call it with a leading slash: App.class.getResource("/view/RootLayout.fxml") then the FXML file has to be in the directory: src/main/resources/view
Double-check if the FXML-file is at the expected location in the JAR-file.
As Puce said, if you call App.class.getResource("view/RootLayout.fxml") then the FXML file has to be in the directory: src/main/resources/mypackage/view where mypackage is the package of the class App.
So , instead of using App.class
FXMLLoader loader = new FXMLLoader();
loader.setLocation(App.class.getResource("view/RootLayout.fxml"));
Try ClassLoader
FXMLLoader loader = new FXMLLoader();
loader.setLocation(ClassLoader.getSystemResource("view/RootLayout.fxml"));
I am having trouble setting up JUnit with App Engine in Eclipse. I have JUnit set up correctly, that is, I can run tests that don't involve the datastore or other services. However, when I try to use the datastore in my tests they fail. The code I am trying right now is from the App Engine site (see below):
http://code.google.com/appengine/docs/java/tools/localunittesting.html#Running_Tests
So far I have added the external JAR (using Eclipse) appengine-testing.jar. But when I run the tests I get the exception below. So, I am clearly not understanding the instructions to enable the services from the web page mentioned above. Can someone clear up the steps needed to make the App Engine services available in Eclipse?
java.lang.NoClassDefFoundError: com/google/appengine/api/datastore/dev/LocalDatastoreService
at com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig.tearDown(LocalDatastoreServiceTestConfig.java:138)
at com.google.appengine.tools.development.testing.LocalServiceTestHelper.tearDown(LocalServiceTestHelper.java:254)
at com.cooperconrad.server.MemberTest.tearDown(MemberTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:37)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.ClassNotFoundException: com.google.appengine.api.datastore.dev.LocalDatastoreService
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
... 25 more
Here is the actual code (pretty much copied from the site):
package com.example;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
public class MemberTest
{
private final LocalServiceTestHelper helper = new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
#Before
public void setUp() {
helper.setUp();
}
#After
public void tearDown() {
helper.tearDown();
}
// run this test twice to prove we're not leaking any state across tests
private void doTest() {
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
assertEquals(0, ds.prepare(new Query("yam")).countEntities());
ds.put(new Entity("yam"));
ds.put(new Entity("yam"));
assertEquals(2, ds.prepare(new Query("yam")).countEntities());
}
#Test
public void testInsert1() {
doTest();
}
#Test
public void testInsert2() {
doTest();
}
#Test
public void foo()
{
assertEquals(4, 2 + 2);
}
}
In Eclipse, have you added all the jars mentioned here? You need a few more jars than just appengine-testing.jar.
However, if your tests or code under test have these dependencies you'll need a few more JARs on your testing classpath: ${SDK_ROOT}/lib/impl/appengine-api.jar, ${SDK_ROOT}/lib/impl/appengine-api-labs.jar, and ${SDK_ROOT}/lib/impl/appengine-api-stubs.jar. These JARs make the runtime APIs and the local implementations of those APIs available to your tests.
Peter's answer is correct: you need these libraries:
appengine-api.jar
appengine-api-labs.jar
appengine-api-stubs.jar
appengine-tools-api.jar
Chances are you already have the first one and only need the last three.
If you're using Maven, you can add these dependencies to pom.xml:
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-labs</artifactId>
<version>1.9.60</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-stubs</artifactId>
<version>1.9.60</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-tools-sdk</artifactId>
<version>1.9.60</version>
<scope>test</scope>
</dependency>