I have a drl file and a .class file in a folder. drl contains rule which is built on class attributes. Now through a java program i want to invoke this rule on some input. I am clueless here . please look at code below
class file
import java.io.Serializable;
public class Txn754909164
implements Serializable
{
String sequenceNo;
String accountNumber;
String customerNumber;
// setter and getters
}
drl file
import Txn754909164;
import java.util.*;
dialect "mvel"
rule "rule6"
when
txn:Txn754909164(sequence == 10)
then
System.out.println( "invoking rule ***********************" );
end
client code
public KieContainer kieContainer(String packageName) {
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
kieFileSystem.write(ResourceFactory.newUrlResource("drl resource url..."));
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem,MyInputClass.getClassLoader());
KieModule kieModule = null;
try {
kieBuilder.buildAll();
kieModule = kieBuilder.getKieModule();
} catch (Exception e) {
e.printStackTrace();
}
return kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId(),cls.getClassLoader());
}
and finally
StatelessKieSession kieSession = container.getKieBase().newStatelessKieSession();
kieSession.execute(obj);
logs
11:47:34.795 [http-nio-8282-exec-4] INFO o.d.c.k.b.impl.KieRepositoryImpl - KieModule was added: MemoryKieModule[releaseId=org.default:artifact:1.0.0-SNAPSHOT]
11:47:34.803 [http-nio-8282-exec-4] TRACE org.drools.core.phreak.AddRemoveRule - Adding Rule rule6
11:47:45.994 [AsyncResolver-bootstrap-executor-0] INFO c.n.d.s.r.aws.ConfigClusterResolver - Resolving eureka endpoints via configuration
11:47:49.899 [http-nio-8282-exec-4] TRACE o.drools.core.reteoo.EntryPointNode - Insert [fact 0:1:1764329060:1764329060:1:DEFAULT:NON_TRAIT:Txn754909164:Txn754909164#69298664]
11:47:52.953 [http-nio-8282-exec-4] INFO o.k.a.e.r.DebugRuleRuntimeEventListener - ==>[ObjectInsertedEventImpl: getFactHandle()=[fact 0:1:1764329060:1764329060:1:DEFAULT:NON_TRAIT:Txn754909164:Txn754909164#69298664], getObject()=Txn754909164#69298664, getKnowledgeRuntime()=KieSession[0], getPropagationContext()=PhreakPropagationContext [entryPoint=EntryPoint::DEFAULT, factHandle=[fact 0:1:1764329060:1764329060:1:DEFAULT:NON_TRAIT:Txn754909164:Txn754909164#69298664], leftTuple=null, originOffset=-1, propagationNumber=2, rule=null, type=INSERTION]]
11:48:41.571 [http-nio-8282-exec-4] DEBUG org.drools.core.common.DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
11:48:41.572 [http-nio-8282-exec-4] TRACE org.drools.core.common.DefaultAgenda - Starting Fire All Rules
11:48:41.573 [http-nio-8282-exec-4] DEBUG org.drools.core.common.DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
11:48:41.573 [http-nio-8282-exec-4] DEBUG org.drools.core.common.DefaultAgenda - State was HALTING is now INACTIVE
11:48:41.574 [http-nio-8282-exec-4] TRACE org.drools.core.common.DefaultAgenda - Ending Fire All Rules
11:48:41.575 [http-nio-8282-exec-4] DEBUG org.drools.core.common.DefaultAgenda - State was INACTIVE is now DISPOSED
It should print statement in then clause of drl rule
above mentioned question and explanation is answer in itself. Found it working perfectly fine from next day. I guess it was just a workspace issue.
Related
I'm trying to use Pi4J to talk to an SPI device where the CS pin is a GPIO pin (GPIO 5) and not one of the mapped CS pins. I don't see how to configure it this way in any of the examples or javadocs. I think it would be somewhere on my SpiConfig line.
// Initialize Pi4J with an auto context
// An auto context includes AUTO-DETECT BINDINGS enabled
// which will load all detected Pi4J extension libraries
// (Platforms and Providers) in the class path
var pi4j = Pi4J.newAutoContext();
// create SPI config
SpiConfig config = Spi.newConfigBuilder(pi4j).id("thermocouple-1")
.name("Thermocouple 1").bus(SpiBus.BUS_1)
.chipSelect(SpiChipSelect.CS_0).build();
// get a SPI I/O provider from the Pi4J context
SpiProvider spiProvider = pi4j.provider("pigpio-spi");
// use try-with-resources to auto-close SPI when complete
try (Spi spi = spiProvider.create(config)) {
byte data[] = new byte[]{0, 0, 0, 0};
It looks like this is possible with v1 of the library, but it's not the same in v2.
I ended up posting on the pi4j project on GitHub and through those conversations worked out what I needed. Here is a cross post from there.
Well looking at the DAC8552 example was the key. Here is a working
version that asks the device for it's ID (register 0xD0) and gives the
correct answer for BME280 (0x60). Thanks for the assist. Here is the
working code (needs to be cleaned up, but it's a basic start).
package com.pi4j.example.spi;
import com.pi4j.Pi4J;
import com.pi4j.context.Context;
import com.pi4j.io.gpio.digital.DigitalOutput;
import com.pi4j.io.gpio.digital.DigitalState;
import com.pi4j.io.spi.Spi;
import com.pi4j.io.spi.SpiBus;
import com.pi4j.io.spi.SpiChipSelect;
import com.pi4j.io.spi.SpiMode;
import com.pi4j.util.Console;
import com.pi4j.util.StringUtil;
public class BmeTest {
private static final SpiBus spiBus = SpiBus.BUS_0;
public static void main(String[] args) throws Exception {
final var console = new Console();
// print program title/header
console.title("<-- The Pi4J Project -->",
"Basic SPI Communications Example");
Context pi4j = Pi4J.newAutoContext();
var spiConfig = Spi.newConfigBuilder(pi4j)
.id("SPI" + spiBus + "_BME280")
.name("BME280")
.bus(spiBus)
.chipSelect(SpiChipSelect.CS_0) // not used
.mode(SpiMode.MODE_0)
.provider("pigpio-spi")
.build();
// required all configs
var outputConfig = DigitalOutput.newConfigBuilder(pi4j)
.id("CS_GPIO5")
.name("CS GPIO5")
.address(5)
.shutdown(DigitalState.HIGH)
.initial(DigitalState.HIGH)
.provider("pigpio-digital-output");
DigitalOutput csGpio = null;
try {
csGpio = pi4j.create(outputConfig);
} catch (Exception e) {
e.printStackTrace();
console.println("create DigOut DRDY failed");
System.exit(202);
}
// use try-with-resources to auto-close SPI when complete
try (var spi = pi4j.create(spiConfig)) {
byte data[] = new byte[] { (byte) (0x80 | 0xD0), (byte) 0x00 };
csGpio.high();
csGpio.low();
spi.transfer(data, data);
csGpio.high();
// take a breath to allow time for the SPI
// data to get updated in the SPI device
Thread.sleep(100);
// read data back from the SPI channel
console.println("--------------------------------------");
console.println("SPI [READ] :");
console.println(" [BYTES] 0x" + StringUtil.toHexString(data));
console.println(" [STRING] " + new String(data));
console.println("--------------------------------------");
}
// shutdown Pi4J
console.println("ATTEMPTING TO SHUTDOWN/TERMINATE THIS PROGRAM");
pi4j.shutdown();
}
}
With the following output:
[main] INFO com.pi4j.util.Console - ************************************************************
[main] INFO com.pi4j.util.Console - ************************************************************
[main] INFO com.pi4j.util.Console -
[main] INFO com.pi4j.util.Console - <-- The Pi4J Project -->
[main] INFO com.pi4j.util.Console - Basic SPI Communications Example
[main] INFO com.pi4j.util.Console -
[main] INFO com.pi4j.util.Console - ************************************************************
[main] INFO com.pi4j.util.Console - ************************************************************
[main] INFO com.pi4j.util.Console -
[main] INFO com.pi4j.Pi4J - New auto context
[main] INFO com.pi4j.Pi4J - New context builder
[main] INFO com.pi4j.platform.impl.DefaultRuntimePlatforms - adding platform to managed platform map [id=raspberrypi; name=RaspberryPi Platform; priority=5; class=com.pi4j.plugin.raspberrypi.platform.RaspberryPiPlatform]
[main] INFO com.pi4j.util.Console - --------------------------------------
[main] INFO com.pi4j.util.Console - SPI [READ] :
[main] INFO com.pi4j.util.Console - [BYTES] 0xFF 60
[main] INFO com.pi4j.util.Console - [STRING] �`
[main] INFO com.pi4j.util.Console - --------------------------------------
[main] INFO com.pi4j.util.Console - ATTEMPTING TO SHUTDOWN/TERMINATE THIS PROGRAM
This is my first time using Scalatra, and I'm using it outside of SBT (building and running using mill). I get the following error which seems to be about a missing dependency.
2018.05.23 18:26:30 [main] INFO org.scalatra.servlet.ScalatraListener - The cycle class name from the config: ScalatraBootstrap
2018.05.23 18:26:30 [main] INFO org.scalatra.servlet.ScalatraListener - Initializing life cycle class: ScalatraBootstrap
2018.05.23 18:26:30 [main] ERROR org.scalatra.servlet.ScalatraListener - Failed to initialize scalatra application at
java.lang.NoSuchMethodError: javax.servlet.ServletContext.getFilterRegistration(Ljava/lang/String;)Ljavax/servlet/FilterRegistration;
at org.scalatra.servlet.RichServletContext.mountFilter(RichServletContext.scala:162)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:85)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:93)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:90)
at ScalatraBootstrap.init(ScalatraBootstrap.scala:8)
at org.scalatra.servlet.ScalatraListener.configureCycleClass(ScalatraListener.scala:66)
at org.scalatra.servlet.ScalatraListener.contextInitialized(ScalatraListener.scala:22)
at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized(ContextHandler.java:890)
at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:558)
at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:853)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:370)
at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1497)
at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1459)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:785)
at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:287)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:545)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:138)
at org.eclipse.jetty.server.Server.start(Server.java:419)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:108)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
at org.eclipse.jetty.server.Server.doStart(Server.java:386)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at com.example.JettyLauncher$.main(JettyLauncher.scala:20)
at com.example.JettyLauncher.main(JettyLauncher.scala)
Here are the dependencies I'm using:
val jettyVersion = "9.4.10.v20180503"
def ivyDeps = Agg(
ivy"org.scalatra::scalatra:2.6.3",
ivy"javax.servlet:servlet-api:2.5",
ivy"org.eclipse.jetty:jetty-server:$jettyVersion",
ivy"org.eclipse.jetty:jetty-servlet:$jettyVersion",
ivy"org.eclipse.jetty:jetty-webapp:$jettyVersion",
)
My JettyLauncher is a striaght copy from the web site, so far, except I changed the resourceBase to be something that actually exists (but it didn't help):
object JettyLauncher { // this is my entry object as specified in sbt project definition
def main(args: Array[String]) {
val port = if(System.getenv("PORT") != null) System.getenv("PORT").toInt else 5001
val server = new Server(port)
val context = new WebAppContext()
context setContextPath "/"
context.setResourceBase("repeater")
context.addEventListener(new ScalatraListener)
context.addServlet(classOf[DefaultServlet], "/")
server.setHandler(context)
server.start
server.join
}
}
My LifeCycle class is also fairly minimal:
class ScalatraBootstrap extends LifeCycle {
override def init(context: ServletContext) {
context mount (new RepeatAll, "/*")
}
}
UPDATE
I changed to using ScalatraServlet instead of ScalatraServlet, but get a similar issue:
2018.05.23 18:39:24 [main] ERROR org.scalatra.servlet.ScalatraListener - Failed to initialize scalatra application at
java.lang.NoSuchMethodError: javax.servlet.ServletContext.getServletRegistration(Ljava/lang/String;)Ljavax/servlet/ServletRegistration;
at org.scalatra.servlet.RichServletContext.mountServlet(RichServletContext.scala:127)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:84)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:93)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:90)
at ScalatraBootstrap.init(ScalatraBootstrap.scala:8)
Update 2
Another important part of the stacktrace I missed posting earlier:
2018.05.23 18:39:24 [main] WARN org.eclipse.jetty.webapp.WebAppContext - Failed startup of context o.e.j.w.WebAppContext#3d74bf60{/,file:///home/brandon/workspace/sbh/repeater,UNAVAILABLE}
java.lang.NoSuchMethodError: javax.servlet.ServletContext.getServletRegistration(Ljava/lang/String;)Ljavax/servlet/ServletRegistration;
at org.scalatra.servlet.RichServletContext.mountServlet(RichServletContext.scala:127)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:84)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:93)
I tried putting a WEB-INF/web.xml under repeater as specified above, but same result.
I have created a fact type( CustomerFact ) with two fact fields(age and bonus) . A sample rule is also created using workbench. Now, I want to inject some test values and check whether the rules are getting fired. I used Eclipse IDE.
I am able to retrieve package name and the rule created in workbench in my java code. However, I am enable to get any fact fields. GetFields always returns an empty list whereas it should have returned 2 fields. Is there any alternative to this? I just want to set the field of the fact type and see whether the rules are getting fired. Any help is highly appreciated.
package org.demo.cityproject;
/**
* This class was automatically generated by the data modeler tool.
*/
public class CustomerFact implements java.io.Serializable
{
static final long serialVersionUID = 1L;
#org.kie.api.definition.type.Key
private int age;
#org.kie.api.definition.type.Key
private int bonus;
public CustomerFact()
{
}
public int getAge()
{
return this.age;
}
public void setAge(int age)
{
this.age = age;
}
public int getBonus()
{
return this.bonus;
}
public void setBonus(int bonus)
{
this.bonus = bonus;
}
public CustomerFact(int age, int bonus)
{
this.age = age;
this.bonus = bonus;
}
#Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
org.demo.cityproject.CustomerFact that = (org.demo.cityproject.CustomerFact) o;
if (age != that.age)
return false;
if (bonus != that.bonus)
return false;
return true;
}
#Override
public int hashCode()
{
int result = 17;
result = 31 * result + age;
result = 31 * result + bonus;
return result;
}
}
Test Code
public static void main(String[] args)
{
String url = "http://localhost:8080/kie-drools-wb-distribution-wars-6.2.0.Final-jboss-as7/maven2/Project1/org/demo/CityProject/1.0/CityProject-1.0.jar";
ReleaseIdImpl releaseId = new ReleaseIdImpl("org.demo", "CityProject", "LATEST");
KieServices kieServices = KieServices.Factory.get();
kieServices.getResources().newUrlResource(url);
KieContainer kieContainer = kieServices.newKieContainer(releaseId);
KieScanner kieScanner = kieServices.newKieScanner(kieContainer);
kieScanner.scanNow();
Scanner scanner = new Scanner(System.in);
System.out.println("kieContainer.getKieBaseNames() "+kieContainer.getKieBaseNames());
KieSession newKieSession =kieContainer.newKieSession("session1");
KieBase lKieBase=newKieSession.getKieBase();
System.out.println("lPackage "+lKieBase.getKiePackages());
KiePackage lPackage=lKieBase.getKiePackage("org.demo.cityproject");
System.out.println("lPackage FactTypes: "+lPackage.getFactTypes());
for(FactType lFact:lPackage.getFactTypes())
{
System.out.println("lFacts: "+lFact.getName());
System.out.println("lFacts Fields: "+lFact.getFields());
}
}
Console o/p in eclipse
22:58:28.998 [main] DEBUG o.d.c.k.b.impl.KieRepositoryImpl - KieModule Lookup. ReleaseId org.demo:CityProject:LATEST was not in cache, checking maven repository
22:58:37.430 [main] DEBUG o.e.a.i.i.DefaultLocalRepositoryProvider - Using manager EnhancedLocalRepositoryManager with priority 10.0 for C:\Users\USER\.m2\repository
22:58:37.743 [main] DEBUG o.e.a.i.i.DefaultLocalRepositoryProvider - Using manager EnhancedLocalRepositoryManager with priority 10.0 for C:\Users\USER\.m2\repository
22:58:39.455 [main] DEBUG o.e.a.i.i.DefaultLocalRepositoryProvider - Using manager EnhancedLocalRepositoryManager with priority 10.0 for C:\Users\USER\.m2\repository
22:58:39.503 [main] DEBUG o.e.a.i.i.DefaultUpdateCheckManager - Skipped remote request for org.demo:CityProject/maven-metadata.xml, locally installed metadata up-to-date.
22:58:39.503 [main] DEBUG o.e.a.i.i.DefaultUpdateCheckManager - Skipped remote request for org.demo:CityProject/maven-metadata.xml, locally installed metadata up-to-date.
22:58:39.503 [main] DEBUG o.e.a.i.i.DefaultUpdateCheckManager - Skipped remote request for org.demo:CityProject/maven-metadata.xml, locally installed metadata up-to-date.
22:58:41.744 [main] DEBUG o.e.a.i.i.DefaultDependencyCollector - Dependency collection stats: {ConflictMarker.analyzeTime=0, ConflictMarker.markTime=0, ConflictMarker.nodeCount=1, ConflictIdSorter.graphTime=0, ConflictIdSorter.topsortTime=0, ConflictIdSorter.conflictIdCount=1, ConflictIdSorter.conflictIdCycleCount=0, ConflictResolver.totalTime=0, ConflictResolver.conflictItemCount=1, DefaultDependencyCollector.collectTime=32, DefaultDependencyCollector.transformTime=15}
22:58:42.230 [main] DEBUG o.e.a.i.i.DefaultLocalRepositoryProvider - Using manager EnhancedLocalRepositoryManager with priority 10.0 for C:\Users\USER\.m2\repository
22:58:42.230 [main] DEBUG o.e.a.i.i.DefaultLocalRepositoryProvider - Using manager EnhancedLocalRepositoryManager with priority 10.0 for C:\Users\USER\.m2\repository
22:58:42.246 [main] DEBUG o.e.a.i.i.DefaultDependencyCollector - Dependency collection stats: {ConflictMarker.analyzeTime=0, ConflictMarker.markTime=0, ConflictMarker.nodeCount=1, ConflictIdSorter.graphTime=0, ConflictIdSorter.topsortTime=0, ConflictIdSorter.conflictIdCount=0, ConflictIdSorter.conflictIdCycleCount=0, ConflictResolver.totalTime=0, ConflictResolver.conflictItemCount=0, DefaultDependencyCollector.collectTime=0, DefaultDependencyCollector.transformTime=0}
22:58:47.596 [main] INFO o.d.c.k.b.impl.KieRepositoryImpl - KieModule was added: ZipKieModule[releaseId=org.demo:CityProject:1.0,file=C:\Users\USER\.m2\repository\org\demo\CityProject\1.0\CityProject-1.0.jar]
22:58:47.957 [main] DEBUG o.e.a.i.i.DefaultLocalRepositoryProvider - Using manager EnhancedLocalRepositoryManager with priority 10.0 for C:\Users\USER\.m2\repository
22:58:47.957 [main] DEBUG o.e.a.i.i.DefaultLocalRepositoryProvider - Using manager EnhancedLocalRepositoryManager with priority 10.0 for C:\Users\USER\.m2\repository
22:58:47.957 [main] DEBUG o.e.a.i.i.DefaultLocalRepositoryProvider - Using manager EnhancedLocalRepositoryManager with priority 10.0 for C:\Users\USER\.m2\repository
22:58:48.426 [main] DEBUG o.e.a.i.i.DefaultLocalRepositoryProvider - Using manager EnhancedLocalRepositoryManager with priority 10.0 for C:\Users\USER\.m2\repository
22:58:48.442 [main] DEBUG o.e.a.i.i.DefaultLocalRepositoryProvider - Using manager EnhancedLocalRepositoryManager with priority 10.0 for C:\Users\USER\.m2\repository
22:58:48.457 [main] DEBUG o.e.a.i.i.DefaultLocalRepositoryProvider - Using manager EnhancedLocalRepositoryManager with priority 10.0 for C:\Users\USER\.m2\repository
22:58:48.457 [main] DEBUG o.e.a.i.i.DefaultUpdateCheckManager - Skipped remote request for org.demo:CityProject/maven-metadata.xml, locally installed metadata up-to-date.
22:58:48.457 [main] DEBUG o.e.a.i.i.DefaultUpdateCheckManager - Skipped remote request for org.demo:CityProject/maven-metadata.xml, locally installed metadata up-to-date.
22:58:48.457 [main] DEBUG o.e.a.i.i.DefaultUpdateCheckManager - Skipped remote request for org.demo:CityProject/maven-metadata.xml, locally installed metadata up-to-date.
kieContainer.getKieBaseNames() [KnowledgeBaseALL]
22:58:50.532 [main] DEBUG o.drools.core.impl.KnowledgeBaseImpl - Starting Engine in PHREAK mode
lPackage [[Package name=org.demo.cityproject]]
lPackage FactTypes: [ClassDefinition{className='org.demo.cityproject.CustomerFact', superClass='java.lang.Object', interfaces=[java.io.Serializable], definedClass=class org.demo.cityproject.CustomerFact, traitable=null, abstract=false, fields={}, annotations=null}]
lFacts: org.demo.cityproject.CustomerFact
**lFacts Fields: []**
As you can see in the output fact field is empty.
The - rather disappointing - situation is that there are two or even three kinds of FactTypes:
Fact types defined by a declare statement in a DRL file
Fact types resulting from Java classes and imported explicitly or implicitly
JDK types used as fact types
Method getFactTypes does not return #3. Method getFields returns an empty list for #2.
Finally I found an answer. Such fields can be invoked by reflection.
Here is how the rules get triggered
for(FactType lFct:lusedpackage.getFactTypes())
{
// System.out.println("Customer class "+lFct.getFactClass());
**Constructor constructor=lFct.getFactClass().getConstructor(String.class,java.math.BigInteger.class);**
**Object s1=constructor.newInstance(lcity,lcustomerID);**
//System.out.println("constructor "+constructor);
//System.out.println("Object "+s1);
**Method lCustID=lFct.getFactClass().getMethod("getCustomerID");**
System.out.println("*************************************************************");
System.out.println("Customer value before firing the rule: "+ lCustID.invoke(s1));
**Method setCity = lFct.getFactClass().getMethod("getCity");**
System.out.println("City value before firing the rule: "+ setCity.invoke(s1));
//System.out.println("method "+lCustID);
System.out.println("*************************************************************");
newKieSession.insert(s1);
newKieSession.fireAllRules();
System.out.println("Customer value after firing the rule: "+ **lCustID.invoke(s1)**);
System.out.println("City value after firing the rule: "+ setCity.invoke(s1));
System.out.println("*************************************************************");
}
I have two almost identical controllers connecting to two different JPA Spring data repositories. The JPA request work correctly, been tested.
I have other request on the same server that works perfectly. Why two different requests that are almost identical don't response with a correct response?
How I can find tips from Spring trace about this problem? I get a Status not found for a request:
type Status report
message /hospital/EditWard/HOSP1/
description The requested resource is not available.
In the console I see this trace:
2015-03-06 11:45:16,686 DEBUG [org.springframework.web.servlet.DispatcherServlet] - DispatcherServlet with name 'dispatcher' processing GET request for [/hospital/EditWard/HOSP1/]
2015-03-06 11:45:16,686 DEBUG [org.springframework.web.servlet.DispatcherServlet] - DispatcherServlet with name 'dispatcher' processing GET request for [/hospital/EditWard/HOSP1/]
2015-03-06 11:45:16,687 DEBUG [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] - Looking up handler method for path /EditWard/HOSP1/
2015-03-06 11:45:16,687 DEBUG [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] - Looking up handler method for path /EditWard/HOSP1/
2015-03-06 11:45:16,689 DEBUG [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] - Did not find handler method for [/EditWard/HOSP1/]
2015-03-06 11:45:16,689 DEBUG [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] - Did not find handler method for [/EditWard/HOSP1/]
2015-03-06 11:45:16,690 DEBUG [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping] - Matching patterns for request [/EditWard/HOSP1/] are [/**]
2015-03-06 11:45:16,690 DEBUG [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping] - Matching patterns for request [/EditWard/HOSP1/] are [/**]
2015-03-06 11:45:16,690 DEBUG [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping] - URI Template variables for request [/EditWard/HOSP1/] are {}
2015-03-06 11:45:16,690 DEBUG [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping] - URI Template variables for request [/EditWard/HOSP1/] are {}
2015-03-06 11:45:16,690 DEBUG [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping] - Mapping [/EditWard/HOSP1/] to HandlerExecutionChain with handler [org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#23c3853d] and 1 interceptor
2015-03-06 11:45:16,690 DEBUG [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping] - Mapping [/EditWard/HOSP1/] to HandlerExecutionChain with handler [org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#23c3853d] and 1 interceptor
2015-03-06 11:45:16,690 DEBUG [org.springframework.web.servlet.DispatcherServlet] - Last-Modified value for [/hospital/EditWard/HOSP1/] is: -1
2015-03-06 11:45:16,690 DEBUG [org.springframework.web.servlet.DispatcherServlet] - Last-Modified value for [/hospital/EditWard/HOSP1/] is: -1
2015-03-06 11:45:16,690 DEBUG [org.springframework.web.servlet.DispatcherServlet] - Null ModelAndView returned to DispatcherServlet with name 'dispatcher': assuming HandlerAdapter completed request handling
2015-03-06 11:45:16,690 DEBUG [org.springframework.web.servlet.DispatcherServlet] - Null ModelAndView returned to DispatcherServlet with name 'dispatcher': assuming HandlerAdapter completed request handling
2015-03-06 11:45:16,690 DEBUG [org.springframework.web.servlet.DispatcherServlet] - Successfully completed request
2015-03-06 11:45:16,690 DEBUG [org.springframework.web.servlet.DispatcherServlet] - Successfully completed request
This is my controller:
package com.freschelegacy.controller;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.freschelegacy.model.Ward;
import com.freschelegacy.model.WardId;
import com.freschelegacy.service.WardService;
import com.freschelegacy.service.data.EditWardDTO;
import com.freschelegacy.service.ServiceException;
import com.freschelegacy.repository.WardRepository;
#RestController()
public class EditWardController {
#Autowired
private WardRepository wardRepository;
#Autowired
private WardService wardService;
private final Logger logger = LoggerFactory.getLogger(EditWardController.class);
#Transactional(readOnly=true)
#RequestMapping(value = "/EditWard", method=RequestMethod.GET, produces = "application/json;charset=utf-8")
public Page<EditWardDTO> getEditWard(#PathVariable String hospitalCode, #RequestParam(value= "page", required = false, defaultValue = "0" ) int page,
#RequestParam(value = "size", required = false, defaultValue = "10" ) int size){
Pageable pageable = new PageRequest(page, size);
Page<EditWardDTO> pageEditWard = wardRepository.editWard(hospitalCode, pageable);
return pageEditWard;
}
}
I have added this /{hospitalCode) to the value of the #Request mapping. Now it works.
#RequestMapping(value ="/EditWard/{hospitalCode}", method=RequestMethod.GET, produces = "application/json;charset=utf-8")
I'm trying to process a file, and upload it into a database, using spring batch, right after uploading it. However the job completes right after it's started, and I'm not too sure of the exact reason. I think it's not doing what it should, in the tasklet.execute. Below is the DEBUG output:
22:25:09.823 [http-nio-127.0.0.1-8080-exec-2] DEBUG o.s.b.c.c.a.SimpleBatchConfiguration$ReferenceTargetSource - Initializing lazy target object
22:25:09.912 [SimpleAsyncTaskExecutor-1] INFO o.s.b.c.l.support.SimpleJobLauncher - Job: [FlowJob: [name=moneyTransactionImport]] launched with the following parameters: [{targetFile=C:\Users\test\AppData\Local\Temp\tomcat.1435325122308787143.8080\uploads\test.csv}]
22:25:09.912 [SimpleAsyncTaskExecutor-1] DEBUG o.s.batch.core.job.AbstractJob - Job execution starting: JobExecution: id=95, version=0, startTime=null, endTime=null, lastUpdated=Tue Sep 16 22:25:09 BST 2014, status=STARTING, exitStatus=exitCode=UNKNOWN;exitDescription=, job=[JobInstance: id=52, version=0, Job=[transactionImport]], jobParameters=[{targetFile=C:\Users\test\AppData\Local\Temp\tomcat.1435325122308787143.8080\uploads\test.csv}]
22:25:09.971 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.c.job.flow.support.SimpleFlow - Resuming state=transactionImport.step with status=UNKNOWN
22:25:09.972 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.c.job.flow.support.SimpleFlow - Handling state=transactionImport.step
22:25:10.018 [SimpleAsyncTaskExecutor-1] INFO o.s.batch.core.job.SimpleStepHandler - Executing step: [step]
22:25:10.019 [SimpleAsyncTaskExecutor-1] DEBUG o.s.batch.core.step.AbstractStep - Executing: id=93
22:25:10.072 [SimpleAsyncTaskExecutor-1] DEBUG o.s.batch.core.scope.StepScope - Creating object in scope=step, name=scopedTarget.reader
22:25:10.117 [SimpleAsyncTaskExecutor-1] DEBUG o.s.batch.core.scope.StepScope - Registered destruction callback in scope=step, name=scopedTarget.reader
22:25:10.136 [SimpleAsyncTaskExecutor-1] WARN o.s.b.item.file.FlatFileItemReader - Input resource does not exist class path resource [C:/Users/test/AppData/Local/Temp/tomcat.1435325122308787143.8080/uploads/test.csv]
22:25:10.180 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.repeat.support.RepeatTemplate - Starting repeat context.
22:25:10.181 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.repeat.support.RepeatTemplate - Repeat operation about to start at count=1
22:25:10.181 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.c.s.c.StepContextRepeatCallback - Preparing chunk execution for StepContext: org.springframework.batch.core.scope.context.StepContext#5d85b879
22:25:10.181 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.c.s.c.StepContextRepeatCallback - Chunk execution starting: queue size=0
22:25:12.333 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.repeat.support.RepeatTemplate - Starting repeat context.
22:25:12.333 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.repeat.support.RepeatTemplate - Repeat operation about to start at count=1
22:25:12.334 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.repeat.support.RepeatTemplate - Repeat is complete according to policy and result value.
22:25:12.334 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.c.s.item.ChunkOrientedTasklet - Inputs not busy, ended: true
22:25:12.334 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.core.step.tasklet.TaskletStep - Applying contribution: [StepContribution: read=0, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
22:25:12.337 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.core.step.tasklet.TaskletStep - Saving step execution before commit: StepExecution: id=93, version=1, name=step, status=STARTED, exitStatus=EXECUTING, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
22:25:12.358 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.repeat.support.RepeatTemplate - Repeat is complete according to policy and result value.
22:25:12.358 [SimpleAsyncTaskExecutor-1] DEBUG o.s.batch.core.step.AbstractStep - Step execution success: id=93
22:25:12.419 [SimpleAsyncTaskExecutor-1] DEBUG o.s.batch.core.step.AbstractStep - Step execution complete: StepExecution: id=93, version=3, name=step, status=COMPLETED, exitStatus=COMPLETED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0
22:25:12.442 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.c.job.flow.support.SimpleFlow - Completed state=transactionImport.step with status=COMPLETED
22:25:12.443 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.c.job.flow.support.SimpleFlow - Handling state=transactionImport.COMPLETED
22:25:12.443 [SimpleAsyncTaskExecutor-1] DEBUG o.s.b.c.job.flow.support.SimpleFlow - Completed state=transactionImport.COMPLETED with status=COMPLETED
22:25:12.445 [SimpleAsyncTaskExecutor-1] DEBUG o.s.batch.core.job.AbstractJob - Job execution complete: JobExecution: id=95, version=1, startTime=Tue Sep 16 22:25:09 BST 2014, endTime=null, lastUpdated=Tue Sep 16 22:25:09 BST 2014, status=COMPLETED, exitStatus=exitCode=COMPLETED;exitDescription=, job=[JobInstance: id=52, version=0, Job=[transactionImport]], jobParameters=[{targetFile=C:\Users\test\AppData\Local\Temp\tomcat.1435325122308787143.8080\uploads\test.csv}]
22:25:12.466 [SimpleAsyncTaskExecutor-1] INFO o.s.b.c.l.support.SimpleJobLauncher - Job: [FlowJob: [name=transactionImport]] completed with the following parameters: [{targetFile=C:\Users\test\AppData\Local\Temp\tomcat.1435325122308787143.8080\uploads\test.csv}] and the following status: [COMPLETED]
My config is as follows:
#Configuration
#EnableBatchProcessing
public class BatchConfiguration {
#Inject
private TransactionRepository transactionRepository;
#Inject
private JobRepository jobRepository;
#Bean
#StepScope
public FlatFileItemReader<MoneyTransaction> reader(#Value("#{jobParameters[targetFile]}") String file) {
FlatFileItemReader<MoneyTransaction> reader = new FlatFileItemReader<>();
reader.setResource(new ClassPathResource(file));
reader.setLineMapper(new DefaultLineMapper<MoneyTransaction>() {
{
setLineTokenizer(new DelimitedLineTokenizer() {
{
setNames(new String[]{"Number", "Date", "Account", "Payee", "Cleared", "Amount", "Category", "Subcategory", "Memo"});
}
}
);
setFieldSetMapper(new BeanWrapperFieldSetMapper<MoneyTransaction>() {
{
setTargetType(MoneyTransaction.class);
}
});
}
}
);
reader.setStrict(false);
reader.setLinesToSkip(1);
return reader;
}
#Bean
public ItemProcessor<MoneyTransaction, Transaction> processor() {
return new TransactionProcessor();
}
#Bean
public RepositoryItemWriter writer() {
RepositoryItemWriter writer = new RepositoryItemWriter();
writer.setRepository(transactionRepository);
writer.setMethodName("save");
return writer;
}
#Bean
public Step step(StepBuilderFactory stepBuilderFactory, ItemReader<MoneyTransaction> reader,
ItemWriter<Transaction> writer, ItemProcessor<MoneyTransaction, Transaction> processor) {
return stepBuilderFactory.get("step")
.<MoneyTransaction, Transaction>chunk(100)
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
#Bean
public SimpleAsyncTaskExecutor taskExecutor() {
SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
executor.setConcurrencyLimit(1);
return executor;
}
#Bean
public SimpleJobLauncher jobLauncher() {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.setTaskExecutor(taskExecutor());
return jobLauncher;
}
}
And I save the file, and start processing in the following way:
public JobExecution processFile(String name, MultipartFile file) {
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
String rootPath = System.getProperty("catalina.home");
File uploadDirectory = new File(rootPath.concat(File.separator).concat("uploads"));
if (!uploadDirectory.exists()) {
uploadDirectory.mkdirs();
}
File uploadFile = new File(uploadDirectory.getAbsolutePath() + File.separator + file.getOriginalFilename());
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(uploadFile));
stream.write(bytes);
stream.close();
return startImportJob(uploadFile, "transactionImport");
} catch (Exception e) {
logger.error(String.format("Error processing file '%s'.", name), e);
throw new MoneyException(e);
}
} else {
throw new MoneyException("There was no file to process.");
}
}
/**
* #param file
*/
private JobExecution startImportJob(File file, String jobName) {
logger.debug(String.format("Starting job to import file '%s'.", file));
try {
Job job = jobs.get(jobName).incrementer(new MoneyRunIdIncrementer()).flow(step).end().build();
return jobLauncher.run(job, new JobParametersBuilder().addString("targetFile", file.getAbsolutePath()).toJobParameters());
} catch (JobExecutionAlreadyRunningException e) {
logger.error(String.format("Job for processing file '%s' is already running.", file), e);
throw new MoneyException(e);
} catch (JobParametersInvalidException e) {
logger.error(String.format("Invalid parameters for processing of file '%s'.", file), e);
throw new MoneyException(e);
} catch (JobRestartException e) {
logger.error(String.format("Error restarting job, for processing file '%s'.", file), e);
throw new MoneyException(e);
} catch (JobInstanceAlreadyCompleteException e) {
logger.error(String.format("Job to process file '%s' has already completed.", file), e);
throw new MoneyException(e);
}
}
I'm kind of stumped at the minute, and any help would be greatly received.
Thanks.
Found the issue. The problem was with the type of resource ClassPathResource(file), combined with the fact that I was setting the strict property to false.
reader.setResource(new ClassPathResource(file));
I should have used
reader.setResource(new FileSystemResource(file));
Which makes complete sense, as I wasn't uploading the file as a class path resource.