Traci4J with SUMO Returning Error - java

I’m very much a novice at both SUMO and Traci4J, however, I am interested in learning how to use these tools. I have ran into a problem when running virtually anything on Traci4J. When performing nextSimStep() on a SumoTraciConnection object I am met with the error
it.polito.appeal.traci.TraCIException$UnexpectedData: Unexpected command/status ID: expected 164, got 2
I cannot find any reason for this occurring, I have attempted it on 2 machines with a clean install of both the latest version of SUMO, the latest version of Traci4J, and Java SE 1.7.
Main method
public static void main(String[] args) {
SumoTraciConnection sumo;
sumo = new SumoTraciConnection(URL_TO_SUMOCFG, (int) System.nanoTime());
sumo.addOption("start", "1");
try {
sumo.runServer(true);
sumo.nextSimStep();
sumo.close();
}catch(IOException | InterruptedException e) {
e.printStackTrace();
}
}
hello.sumocfg File
<input>
<net-file value="hello.net.xml"/>
<route-files value="hello.rou.xml"/>
</input>
<time>
<begin value="0"/>
<end value="10000"/>
</time>
<gui_only>
<gui-settings-file value="hello.settings.xml"/>
</gui_only>
hello.net.xml File
<?xml version="1.0" encoding="UTF-8"?>
-->
<location netOffset="250.00,0.00" convBoundary="0.00,-71.61,501.00,0.00" origBoundary="-250.00,0.00,251.00,0.00" projParameter="!"/>
<edge id=":2_0" function="internal">
<lane id=":2_0_0" index="0" speed="13.90" length="0.10" shape="500.00,-1.65 500.00,-1.65"/>
</edge>
<edge id="1to2" from="1" to="2" priority="-1">
<lane id="1to2_0" index="0" speed="13.90" length="500.00" shape="0.00,-1.65 500.00,-1.65"/>
</edge>
<edge id="gneE0" from="gneJ0" to="gneJ1" priority="1">
<lane id="gneE0_0" index="0" speed="13.89" length="153.61" shape="227.09,-64.38 380.45,-73.25"/>
</edge>
<edge id="out" from="2" to="3" priority="-1">
<lane id="out_0" index="0" speed="13.90" length="1.00" shape="500.00,-1.65 501.00,-1.65"/>
</edge>
<junction id="1" type="dead_end" x="0.00" y="0.00" incLanes="" intLanes="" shape="0.00,-0.05 0.00,-3.25"/>
<junction id="2" type="priority" x="500.00" y="0.00" incLanes="1to2_0" intLanes=":2_0_0" shape="500.00,-0.05 500.00,-3.25 500.00,-0.05">
<request index="0" response="0" foes="0" cont="0"/>
</junction>
<junction id="3" type="dead_end" x="501.00" y="0.00" incLanes="out_0" intLanes="" shape="501.00,-3.25 501.00,-0.05"/>
<junction id="gneJ0" type="dead_end" x="227.19" y="-62.74" incLanes="" intLanes="" shape="227.18,-62.79 227.00,-65.98"/>
<junction id="gneJ1" type="dead_end" x="380.54" y="-71.61" incLanes="gneE0_0" intLanes="" shape="380.35,-74.85 380.54,-71.66"/>
<connection from="1to2" to="out" fromLane="0" toLane="0" via=":2_0_0" dir="s" state="M"/>
<connection from=":2_0" to="out" fromLane="0" toLane="0" dir="s" state="M"/>
hello.rou.xml File
<?xml version="1.0" encoding="UTF-8"?>
<!-- generated on 14/02/2018 21:20:37 by Netedit Version 0.31.0
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.dlr.de/xsd/netconvertConfiguration.xsd">
<input>
<sumo-net-file value="hello.net.xml"/>
</input>
<output>
<output-file value="hello.net.xml"/>
</output>
<processing>
<no-turnarounds value="true"/>
<offset.disable-normalization value="true"/>
<lefthand value="false"/>
<junctions.corner-detail value="0"/>
<rectangular-lane-cut value="false"/>
<walkingareas value="false"/>
</processing>
<visualisation>
<registry-viewport value="true"/>
</visualisation>
</configuration>
-->
<net version="0.27" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.dlr.de/xsd/net_file.xsd">
<location netOffset="250.00,0.00" convBoundary="0.00,-71.61,501.00,0.00" origBoundary="-250.00,0.00,251.00,0.00" projParameter="!"/>
<edge id=":2_0" function="internal">
<lane id=":2_0_0" index="0" speed="13.90" length="0.10" shape="500.00,-1.65 500.00,-1.65"/>
</edge>
<edge id="1to2" from="1" to="2" priority="-1">
<lane id="1to2_0" index="0" speed="13.90" length="500.00" shape="0.00,-1.65 500.00,-1.65"/>
</edge>
<edge id="gneE0" from="gneJ0" to="gneJ1" priority="1">
<lane id="gneE0_0" index="0" speed="13.89" length="153.61" shape="227.09,-64.38 380.45,-73.25"/>
</edge>
<edge id="out" from="2" to="3" priority="-1">
<lane id="out_0" index="0" speed="13.90" length="1.00" shape="500.00,-1.65 501.00,-1.65"/>
</edge>
<junction id="1" type="dead_end" x="0.00" y="0.00" incLanes="" intLanes="" shape="0.00,-0.05 0.00,-3.25"/>
<junction id="2" type="priority" x="500.00" y="0.00" incLanes="1to2_0" intLanes=":2_0_0" shape="500.00,-0.05 500.00,-3.25 500.00,-0.05">
<request index="0" response="0" foes="0" cont="0"/>
</junction>
<junction id="3" type="dead_end" x="501.00" y="0.00" incLanes="out_0" intLanes="" shape="501.00,-3.25 501.00,-0.05"/>
<junction id="gneJ0" type="dead_end" x="227.19" y="-62.74" incLanes="" intLanes="" shape="227.18,-62.79 227.00,-65.98"/>
<junction id="gneJ1" type="dead_end" x="380.54" y="-71.61" incLanes="gneE0_0" intLanes="" shape="380.35,-74.85 380.54,-71.66"/>
<connection from="1to2" to="out" fromLane="0" toLane="0" via=":2_0_0" dir="s" state="M"/>
<connection from=":2_0" to="out" fromLane="0" toLane="0" dir="s" state="M"/>
</net>
Error Message Trace
it.polito.appeal.traci.TraCIException$UnexpectedData: Unexpected command/status ID: expected 164, got 2
at it.polito.appeal.traci.Utils.checkStatusResponse(Utils.java:57)
at it.polito.appeal.traci.ChangeStateQuery.pickResponses(ChangeStateQuery.java:83)
at it.polito.appeal.traci.MultiQuery.run(MultiQuery.java:108)
at it.polito.appeal.traci.SumoTraciConnection.nextSimStep(SumoTraciConnection.java:623)
at it.polito.appeal.traci.test.TraCITest.getFirstVehicle(TraCITest.java:337)
at it.polito.appeal.traci.test.TraCITest.testChangeTarget(TraCITest.java:577)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
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.junit.runners.ParentRunner.run(ParentRunner.java:363)
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)
I'm sorry if this is verbose, any help would be hugely appreciated

I meet the same question with using the Traci4J.
If you want to use Traas, I can give you some tips.
You could find the WebService class here:
traas/src/main/java/de/tudresden/ws/WebService.java
This is an executable java file. Then you will get a running server. If you create a web service client, you could connect with the traas server and do the simulation with sumo. Btw I still have some doubt that the api of traas is less than the api for python and C++;
Here is a small demo, supposing that you have already imported the traas.jar;
public class MyWebService {
public static void main(String[] args) {
Config.config_file = "resources/map.sumo.cfg";
de.tudresden.ws.WebService.main(new String[]{});
}
}
The web service client:
public class HelloWorldClient {
public static TraasWSLocator locator;
public static ServiceImpl service;
static {
try {
locator = new TraasWSLocator();
service = locator.getServiceImplPort();
}
catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] argv) throws RemoteException{
service.setSumoBinary("sumo-gui");
service.start("username");
while (service.simulation_getMinExpectedNumber()>0){
service.doTimestep();
}
}
}

Related

Error Decrypting SAML Assertion with OpenSAM:

I have an application integrating with another using SAML. I am using OpenSAML2, and sent the IDP our metadata so they can encrypt their data. We got a response, and I'm able to decode it, and it seems to be a valid Response:
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" Destination="<DESTINATION>" ID="_e344fa7e-59b4-480a-9d89-998abf933b4f" InResponseTo="_60f946e65b26d30b69857e8718dca1ca" IssueInstant="2018-10-30T22:14:46.943Z" Version="2.0">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">ISSUER</Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<EncryptedAssertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<e:EncryptedKey xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
</e:EncryptionMethod>
<KeyInfo>
<ds:X509Data xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509IssuerSerial>
<ds:X509IssuerName>ISSUER</ds:X509IssuerName>
<ds:X509SerialNumber>355107170</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data>
</KeyInfo>
<e:CipherData>
<e:CipherValue>CIPHER VALUE</e:CipherValue>
</e:CipherData>
</e:EncryptedKey>
</KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>CIPHER VALUE</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</EncryptedAssertion>
And here's how I'm decrypting
public Assertion decryptAssertion(EncryptedAssertion encryptedAssertion) throws RondoSsoException {
try {
//Security.insertProviderAt(new BouncyCastleProvider(), 1);
final List<EncryptedKeyResolver> list = new ArrayList<>();
list.add(new InlineEncryptedKeyResolver());
list.add(new EncryptedElementTypeEncryptedKeyResolver());
list.add(new SimpleRetrievalMethodEncryptedKeyResolver());
ChainingEncryptedKeyResolver encryptedKeyResolver = new ChainingEncryptedKeyResolver(list);
Credential credential = generateCredentialFromKeystore();
KeyInfoCredentialResolver resolver = new StaticKeyInfoCredentialResolver(credential);
Decrypter decrypter = new Decrypter(null, resolver, encryptedKeyResolver);
decrypter.setRootInNewDocument(true);
return decrypter.decrypt(encryptedAssertion);
} catch (RondoSsoException | DecryptionException e) {
throw new RondoSsoException("Error decrypting assertion", e);
}
}
The crendetials being generated this way from a JKS keystore:
public BasicX509Credential generateX509CredentialFromJKS() throws SecurityException, ResolverException {
Map<String, String> passwordMap = new HashMap<String, String>();
passwordMap.put(ssoProperties.getProperty(CERT_NAME), ssoProperties.getProperty(CERT_PASSWORD));
KeyStoreCredentialResolver resolver = new KeyStoreCredentialResolver(getKeyStore(), passwordMap);
EntityIdCriterion criterion = new EntityIdCriterion(ssoProperties.getProperty(CERT_NAME));
CriteriaSet criteriaSet = new CriteriaSet();
criteriaSet.add(criterion);
return (BasicX509Credential) resolver.resolveSingle(criteriaSet);
}
Which generates this error.
java.security.InvalidKeyException: Unwrapping failed
at com.sun.crypto.provider.RSACipher.engineUnwrap(RSACipher.java:445)
at javax.crypto.Cipher.unwrap(Cipher.java:2549)
at org.apache.xml.security.encryption.XMLCipher.decryptKey(XMLCipher.java:1466)
at org.opensaml.xmlsec.encryption.support.Decrypter.decryptKey(Decrypter.java:711)
at org.opensaml.xmlsec.encryption.support.Decrypter.decryptKey(Decrypter.java:643)
at org.opensaml.xmlsec.encryption.support.Decrypter.decryptUsingResolvedEncryptedKey(Decrypter.java:781)
at org.opensaml.xmlsec.encryption.support.Decrypter.decryptDataToDOM(Decrypter.java:539)
at org.opensaml.xmlsec.encryption.support.Decrypter.decryptDataToList(Decrypter.java:452)
at org.opensaml.xmlsec.encryption.support.Decrypter.decryptData(Decrypter.java:412)
at org.opensaml.saml.saml2.encryption.Decrypter.decryptData(Decrypter.java:176)
at org.opensaml.saml.saml2.encryption.Decrypter.decrypt(Decrypter.java:104)
at com.casebank.rondo.sso.service.saml2.Saml2SecurityAndEncryptionManager.decryptAssertion(Saml2SecurityAndEncryptionManager.java:436)
at com.casebank.rondo.sso.service.saml2.Saml2SSOProcessor.parseSAMLAssertion(Saml2SSOProcessor.java:483)
at com.casebank.rondo.sso.service.saml2.Saml2SSOProcessor.processLogon(Saml2SSOProcessor.java:501)
at com.casebank.rondo.sso.service.Saml2SSOProcessorTest.testProcessResponse(Saml2SSOProcessorTest.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
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:191)
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:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadOAEP(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
at com.sun.crypto.provider.RSACipher.engineUnwrap(RSACipher.java:440)
... 43 more
I have tried finding solutions here, and found other posts like this one regarding cryptography strength, that was addressed already or this one, but this assertion was missing the namespace, which is not my case.
My main problem is that the exception does not specify exactly what is going wrong (key size, padding or other issues). I even verified the size of the encrypted data, and it's 256, as expected. I've been doing research for a while without any possible solutions. Any help is greatly appreciated.

how to make a form field of type List<Inventory> for camunda rest api

We're going to build a workflow management system and We're embedding the camunda engine Rest API into our Rest Application.
Now I have Inventory defined like this:
public class Inventory {
private String objectName;
private int objectCount;
// getters and setters
}
and this is a sample workflow:
in xml:
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="1.11.3">
<bpmn:process id="test" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>SequenceFlow_1v6clcy</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="SequenceFlow_1v6clcy" sourceRef="StartEvent_1" targetRef="testtask" />
<bpmn:userTask id="testtask" name="testtask" camunda:formKey="testform">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="inventories" label="name" type="List<org.example.Inventory>" />
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>SequenceFlow_1v6clcy</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_07kdfp4</bpmn:outgoing>
</bpmn:userTask>
<bpmn:endEvent id="EndEvent_0vm605w">
<bpmn:incoming>SequenceFlow_07kdfp4</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="SequenceFlow_07kdfp4" sourceRef="testtask" targetRef="EndEvent_0vm605w" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="test">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="173" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1v6clcy_di" bpmnElement="SequenceFlow_1v6clcy">
<di:waypoint xsi:type="dc:Point" x="209" y="120" />
<di:waypoint xsi:type="dc:Point" x="275" y="120" />
<bpmndi:BPMNLabel>
<dc:Bounds x="242" y="99" width="0" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="UserTask_1s01hea_di" bpmnElement="testtask">
<dc:Bounds x="275" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_0vm605w_di" bpmnElement="EndEvent_0vm605w">
<dc:Bounds x="439" y="109" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="412" y="149" width="90" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_07kdfp4_di" bpmnElement="SequenceFlow_07kdfp4">
<di:waypoint xsi:type="dc:Point" x="375" y="120" />
<di:waypoint xsi:type="dc:Point" x="407" y="120" />
<di:waypoint xsi:type="dc:Point" x="407" y="127" />
<di:waypoint xsi:type="dc:Point" x="439" y="127" />
<bpmndi:BPMNLabel>
<dc:Bounds x="377" y="117.5" width="90" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
I'll eventually have a html form which will submit something like this:
{
"inventories" : [{"name": "banana","count": 3},{"name":"orange","count": 4}]
}
I want to submit this to /task/{id}/submit-form but I don't know what to put as type.
I tried putting the type in modeler as List<org.example.Inventory> but the rest api throws an exception when deploying the process definition like this:
org.camunda.bpm.engine.ProcessEngineException: ENGINE-09005 Could not parse BPMN process. Errors:
* unknown type 'List' | org.example/PM.bpmn | line 65 | column 90
I've seen this example as well but I'm only using the Rest API not the whole bpm platform(besides we prefer to have pure html forms).
So how to do it ? what should I put in type ?
my camunda.cfg.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="processEngineConfiguration" class="org.camunda.bpm.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcUrl" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
<property name="jdbcDriver" value="org.h2.Driver" />
<property name="jdbcUsername" value="sa" />
<property name="jdbcPassword" value="" />
<property name="databaseSchemaUpdate" value="true" />
</bean>
</beans>
my processengineprovider:
public class MyProcessEngineProvider implements ProcessEngineProvider {
#Override
public ProcessEngine getDefaultProcessEngine() {
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = engine.getRepositoryService();
repositoryService.createDeployment()
.addClasspathResource("org.newtech/PM.bpmn")
.deploy();
return engine;
}
#Override
public ProcessEngine getProcessEngine(String s) {
return getDefaultProcessEngine();
}
#Override
public Set<String> getProcessEngineNames() {
Set<String> names = new HashSet<>(1);
names.add("default");
return names;
}
}

redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool

redis.properties
#jedisPoolConfig
redis.minIdle=100
redis.maxIdle=500
redis.maxTotal=50000
redis.maxWaitMillis=10000
redis.testOnBorrow=true
#jedisPool
redis.host=192.168.13.169
redis.port=6379
redis.timeout=3000
redis.port2=6380
#redis-sentinel
redis.sentinel=192.168.13.169:26379
redis.master=mymaster
spring-redis.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--properties配置-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:redis.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
<!-- 连接池配置信息 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxTotal" value="${redis.maxTotal}" />
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<!--初级版:单实例-->
<bean id="jedisPool" class="redis.clients.jedis.JedisPool" scope="singleton">
<constructor-arg name="poolConfig" ref="jedisPoolConfig" />
<constructor-arg name="host" value="${redis.host}" />
<constructor-arg name="port" value="${redis.port}" type="int" />
</bean>
<!--主从-->
<bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1">
<list>
<bean class="redis.clients.jedis.JedisShardInfo">
<constructor-arg name="host" value="${redis.host}" />
<constructor-arg name="port" value="${redis.port}" />
<constructor-arg name="timeout" value="${redis.timeout}" />
<constructor-arg name="name" value="master" />
</bean>
<bean class="redis.clients.jedis.JedisShardInfo">
<constructor-arg name="host" value="${redis.host}" />
<constructor-arg name="port" value="${redis.port2}" />
<constructor-arg name="timeout" value="${redis.timeout}" />
<constructor-arg name="name" value="slave1" />
</bean>
</list>
</constructor-arg>
</bean>
<!--sentinel模式-->
<bean id="redisSentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
<constructor-arg name="master" value="${redis.master}" />
<constructor-arg name="sentinelHostAndPorts">
<set>
<value>${redis.sentinel}</value>
</set>
</constructor-arg>
</bean>
<!--Jedis连接池-->
<bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:use-pool="true">
<property name="hostName" value="${redis.host}"/>
<constructor-arg ref="redisSentinelConfiguration" />
<constructor-arg ref="jedisPoolConfig" />
</bean>
<!-- redis template definition -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" p:connection-factory-ref="jedisConnFactory"/>
<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
Code
Controller
#Controller
public class JedisController {
......
#Autowired
private RedisService redisService;
#RequestMapping(value = "test2")
#ResponseBody
public String test2(){
redisService.set("key2","v2");
return redisService.get("key1");
}
......
}
Service
#Service
public class RedisService extends BinaryRedisService {
public RedisService() {}
public String set(final String key, final String value) {
return (String)this.execute(new Function<ShardedJedis, String>() {
public String callBack(ShardedJedis shardedJedis) {
return shardedJedis.set(key, value);
}
});
}
......
}
public class BinaryRedisService {
#Autowired
protected ShardedJedisPool shardedJedisPool;
public BinaryRedisService() {
}
protected <T> T execute(Function<ShardedJedis, T> fun) {
ShardedJedis shardedJedis = null;
T t = null;
try {
shardedJedis = this.shardedJedisPool.getResource();
t = fun.callBack(shardedJedis);
} catch (Exception var8) {
var8.printStackTrace();
} finally {
if(null != shardedJedis) {
shardedJedis.close();
}
return t;
}
}
......
}
Problem
redis.clients.jedis.exceptions.JedisException: Could not get a
resource from the pool at
redis.clients.util.Pool.getResource(Pool.java:51) at
redis.clients.jedis.ShardedJedisPool.getResource(ShardedJedisPool.java:36)
at
org.henry.service.BinaryRedisService.execute(BinaryRedisService.java:29)
at org.henry.service.RedisService.set(RedisService.java:25) at
org.henry.service.RedisService$$FastClassBySpringCGLIB$$f57afd3.invoke()
at
org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)
at
org.henry.service.RedisService$$EnhancerBySpringCGLIB$$d4e52321.set()
at
org.henry.controller.JedisController.test2(JedisController.java:51)
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:497) at
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
at
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
at
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
at
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) at
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at
org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:837)
at
org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:583)
at
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at
org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
at
org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
at
org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
at
org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
at
org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at
org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
at
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at
org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)
at
org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:119)
at
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.eclipse.jetty.server.Server.handle(Server.java:524) at
org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319) at
org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
at
org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
at
org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
at
org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
at
org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
at
org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
at
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at
org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:745) Caused by:
java.util.NoSuchElementException: Unable to validate object at
org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:506)
at
org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363)
at redis.clients.util.Pool.getResource(Pool.java:49) ... 58 more
You need to make sure that a) Redis is running b) that it is able to accept connections from remote hosts and c) if you have enabled password protection, provide a password in your code.
To make sure that it can accept connections from remote hosts you have to look at the redis.conf file. Find the line with the binding addresses (it should look something like: bind 127.0.0.1) and either comment it out (so it can accept requests from all remote hosts - not recommended for production, but it's OK for testing), or add the remote IPs you want your Redis service to accept connections from.

Spring Framework integration test Java [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 7 years ago.
I wrote an integration test on a Spring Framework controller and the and test runs correct. Application runs correct too. I have some exceptions that i want to fix. I can not fix the nullpoiner exception which come from LoginController at line 34. I saw that loginDelegate but how ti fix this ?
Controller class
#Controller
public class LoginController {
#Autowired
private LoginDelegate loginDelegate;
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView displayLogin(HttpServletRequest request, HttpServletResponse response, LoginBean loginBean) {
ModelAndView model = new ModelAndView("login");
model.addObject("loginBean", loginBean);
return model;
}
#RequestMapping(value = "/login", method = RequestMethod.POST)
public ModelAndView executeLogin(ModelAndView model, HttpServletRequest request, HttpServletResponse response,
#ModelAttribute("loginBean") LoginBean loginBean) {
try {
boolean isValidUser = loginDelegate.isValidUser(loginBean.getUsername(), loginBean.getPassword());
if (isValidUser) {
System.out.println("User Login Successful");
request.setAttribute("loggedInUser", loginBean.getUsername());
model = new ModelAndView("welcome");
} else {
model = new ModelAndView("login");
request.setAttribute("message", "Invalid credentials!!");
}
} catch (Exception e) {
e.printStackTrace();
}
return model;
}
}
Test Controller Class
#EnableWebMvc
#WebAppConfiguration
#Configuration
#ContextConfiguration(locations = { "classpath:/WEB-INF/spring-dispatcher-servlet.xml" })
public class LoginControllerTest {
#Autowired
protected WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setup() throws Exception {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
this.mockMvc = standaloneSetup(new LoginController()).setViewResolvers(viewResolver).build();
}
#Test
public void testDisplayLogin() throws Exception {
this.mockMvc.perform(get("/login")).andExpect(status().isOk()).andExpect(view().name("login")).andDo(print())
.andExpect(forwardedUrl("/WEB-INF/views/login.jsp"));
}
#Test
public void testExecuteLogin() throws Exception {
this.mockMvc.perform(post("/login").param("username", "nikola").param("password", "pass")).andDo(print())
.andExpect(status().isOk()).andExpect(view().name("login"));
}
}
spring dispacher servlet
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.nikola" />
<mvc:annotation-driven enable-matrix-variables="true" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="loginDelegate" class="com.nikola.integration.delegate.LoginDelegate">
<property name="userService" ref="userService"></property>
</bean>
<bean id="userService" class="com.nikola.integration.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<bean name="userDao" class="com.nikola.integration.dao.impl.UserDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean name="loginController" class="com.nikola.integration.controller.LoginController">
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/store" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
</beans>
Exception
java.lang.NullPointerException
at com.nikola.integration.controller.LoginController.executeLogin(LoginController.java:34)
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:497)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:111)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:144)
at com.nikola.integration.controller.test.LoginControllerTest.testExecuteLogin(LoginControllerTest.java:51)
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:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
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.junit.runners.ParentRunner.run(ParentRunner.java:363)
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)
In your test, you are instantiating a new LoginController :
this.mockMvc = standaloneSetup(new LoginController()).setViewResolvers(viewResolver).build();
This new instance is not managed by spring and the #Autowired field is not injected.
You should inject in your test the LoginController defined in your configuration, and initialize the mockMvc with this instance :
#Autowired
private LoginController controller;
...
this.mockMvc = standaloneSetup(c).setViewResolvers(viewResolver).build();

Spring Batch: not able to access jobexecutionConext in flatfileitemwriter

hey i am trying to use the jobexecutioncontxt in my flatfileitemwriter and it shows me errors...
My xml is:-
<batch:job id="subrogationJob" incrementer="incrementer">
<batch:step id="subrogation" next="readFromDataBase">
<batch:tasklet ref="filetransferTasklet">
<batch:listeners>
<batch:listener ref="setCurrentFile" />
</batch:listeners>
</batch:tasklet>
</batch:step>
<batch:step id="readFromDataBase" next="hasMoreFilesStep">
<batch:tasklet>
<batch:chunk reader="databaseReader" processor="subrogationProcessor" writer="dbToFileItemWriter"
commit-interval="1" />
</batch:tasklet>
</batch:step>
<batch:decision id="hasMoreFilesStep" decider="hasMoreFilesDecider">
<batch:fail on="FAILED" />
<batch:next on="CONTINUE" to="subrogation" />
<batch:end on="COMPLETED"/>
</batch:decision>
</batch:job>
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations"
value="file:${UNIQUE_DIR}/${APP_NAME}/batch/nonadj_batch.properties" />
</bean>
<bean id="incrementer"
class="org.springframework.batch.core.launch.support.RunIdIncrementer" />
<bean id="setCurrentFile"
class="com.hcsc.ccsp.nonadj.subrogation.batch.SubrogationInputFolderScanner"
scope="step">
<property name="collectionParameter" value="inputFiles" />
<property name="outputFolder" value="${subrogationOutputFolder}" />
<property name="inputFolder" value="${subrogationInputFolder}" />
<property name="archiveFolder" value="${subrogationArchiveFolder}" />
</bean>
<bean id="filetransferTasklet"
class="com.hcsc.ccsp.nonadj.subrogation.integration.SubrogationFileTransferTasklet"
scope="step">
<property name="inputfile" value="file:#{jobExecutionContext['inputFile']}" />
<property name="outputfile" value="file:#{jobExecutionContext['outputFile']}" />
</bean>
<bean id="subrogationProcessor" class="com.hcsc.ccsp.nonadj.subrogation.processor.SubrogationProcessor" scope="step">
</bean>
<bean id="dbToFileItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
<property name="resource" value="file:#{jobExecutionContext['outputFile']}" />
<property name="lineAggregator">
<bean class="com.hcsc.ccsp.nonadj.subrogation.writer.SubrogationLineAggregator"/>
</property>
<property name="footerCallback" ref="subroHeaderFooterWriter" />
<property name="headerCallback" ref="subroHeaderFooterWriter" />
<property name="transactional" value="true" />
<property name="appendAllowed" value="true" />
<property name="saveState" value="true" />
</bean>
<bean id="subroHeaderFooterWriter" class="com.hcsc.ccsp.nonadj.subrogation.writer.SubrogationHeaderFooterWriter" scope="step">
<property name="delegate" ref="dbToFileItemWriter" />
</bean>
<bean id="hasMoreFilesDecider"
class="com.hcsc.ccsp.nonadj.subrogation.batch.CollectionEmptyDecider" scope="step">
<property name="collectionParameter" value="inputFiles" />
<property name="outputfile" value="file:#{jobExecutionContext['outputFile']}" />
<property name="archiveFolder" value="file:${subrogationArchiveFolder}" />
</bean>
<context:component-scan base-package="com.hcsc.ccsp.nonadj.subrogation.batch"
use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Component" />
</context:component-scan>
<context:annotation-config />
<bean id="databaseReader"
class="org.springframework.batch.item.database.JdbcCursorItemReader"
scope="step">
<property name="dataSource" ref="subrogrationDataSource" />
<property name="sql"
value="SELECT QUERY" />
<property name="rowMapper">
<bean
class="com.hcsc.ccsp.nonadj.subrogation.integration.SubrogationFieldSetMapper" />
</property>
</bean>
in my listner in beforestep i put parameter in jobcontextn as
ExecutionContext jobContext = stepExecution.getJobExecution().getExecutionContext();
jobContext.put("outputFile", filePath);
and in xml when i m trying to use this in xml in my writer is shows me error.....
but it works fine filetransferTasklet.
error is :-
O inside reader
[5/1/14 10:41:02:303 CDT] 0000001a SystemOut O inside processor........
[5/1/14 10:41:02:303 CDT] 0000001a SystemOut O inside aggregator
[5/1/14 10:41:02:320 CDT] 0000001a AbstractStep E org.springframework.batch.core.step.AbstractStep execute Exception while closing step execution resources
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.subroHeaderFooterWriter' defined in class path resource [subrogation.xml]: Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type '$Proxy46 implementing org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,org.springframework.beans.factory.InitializingBean,java.io.Serializable,org.springframework.aop.scope.ScopedObject,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'org.springframework.batch.item.file.FlatFileItemWriter' for property 'delegate'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [$Proxy46 implementing org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,org.springframework.beans.factory.InitializingBean,java.io.Serializable,org.springframework.aop.scope.ScopedObject,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.batch.item.file.FlatFileItemWriter] for property 'delegate': no matching editors or conversion strategy found
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:329)
at org.springframework.batch.core.scope.StepScope.get(StepScope.java:150)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:325)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:33)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:182)
at $Proxy47.writeFooter(Unknown Source)
at org.springframework.batch.item.file.FlatFileItemWriter.close(FlatFileItemWriter.java:282)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:600)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy46.close(Unknown Source)
at org.springframework.batch.item.support.CompositeItemStream.close(CompositeItemStream.java:83)
at org.springframework.batch.core.step.tasklet.TaskletStep.close(TaskletStep.java:297)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:264)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:293)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:114)
at com.hcsc.ccsp.nonadj.batch.web.JobLauncherController.launch(JobLauncherController.java:64)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:600)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:718)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1661)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:937)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:500)
at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:178)
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3826)
at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:276)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:931)
at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1583)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:186)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:455)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:384)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:272)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1550)
Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type '$Proxy46 implementing org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,org.springframework.beans.factory.InitializingBean,java.io.Serializable,org.springframework.aop.scope.ScopedObject,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'org.springframework.batch.item.file.FlatFileItemWriter' for property 'delegate'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [$Proxy46 implementing org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,org.springframework.beans.factory.InitializingBean,java.io.Serializable,org.springframework.aop.scope.ScopedObject,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.batch.item.file.FlatFileItemWriter] for property 'delegate': no matching editors or conversion strategy found
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:462)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:499)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:493)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1371)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1330)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1086)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
... 70 more
Caused by: java.lang.IllegalStateException: Cannot convert value of type [$Proxy46 implementing org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,org.springframework.beans.factory.InitializingBean,java.io.Serializable,org.springframework.aop.scope.ScopedObject,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.batch.item.file.FlatFileItemWriter] for property 'delegate': no matching editors or conversion strategy found
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:231)
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:447)
... 76 more
[5/1/14 10:41:02:386 CDT] 0000001a AbstractJob E org.springframework.batch.core.job.AbstractJob execute Encountered fatal error executing job
org.springframework.batch.core.JobExecutionException: Flow execution ended unexpectedly
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:141)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:293)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:114)
at com.hcsc.ccsp.nonadj.batch.web.JobLauncherController.launch(JobLauncherController.java:64)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:600)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:718)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1661)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:937)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:500)
at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:178)
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3826)
at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:276)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:931)
at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1583)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:186)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:455)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:384)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:272)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1550)
Caused by: org.springframework.batch.core.job.flow.FlowExecutionException: Ended flow=subrogationJob at state=subrogationJob.hasMoreFilesStep with exception
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:152)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
... 40 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.hasMoreFilesDecider': Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for step scope
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:339)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:33)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:182)
at $Proxy45.decide(Unknown Source)
at org.springframework.batch.core.job.flow.support.state.DecisionState.handle(DecisionState.java:43)
at org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean$DelegateState.handle(SimpleFlowFactoryBean.java:141)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
... 42 more
Caused by: java.lang.IllegalStateException: No context holder available for step scope
at org.springframework.batch.core.scope.StepScope.getContext(StepScope.java:197)
at org.springframework.batch.core.scope.StepScope.get(StepScope.java:139)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:325)
... 49 more
[5/1/14 10:41:02:392 CDT] 0000001a SimpleJobLaun I org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run Job: [FlowJob: [name=subrogationJob]] completed with the following parameters: [{param47=47}] and the following status: [FAILED]
SubrogationHeaderFooterWriter is
package com.hcsc.ccsp.nonadj.subrogation.writer;
import java.io.IOException;
import java.io.Writer;
import org.apache.commons.lang3.StringUtils;
import org.springframework.batch.item.file.FlatFileFooterCallback;
import org.springframework.batch.item.file.FlatFileHeaderCallback;
import org.springframework.batch.item.file.FlatFileItemWriter;
import com.hcsc.ccsp.nonadj.subrogation.batch.Subrogation;
import com.hcsc.ccsp.nonadj.subrogation.integration.SubrogationFileTransferTasklet;
import com.hcsc.ccsp.nonadj.subrogation.processor.SubrogationProcessor;
public class SubrogationHeaderFooterWriter implements
FlatFileFooterCallback, FlatFileHeaderCallback{
SubrogationFileTransferTasklet fileTransferTasklet = new SubrogationFileTransferTasklet();
private FlatFileItemWriter<Subrogation> delegate;
public void setDelegate(FlatFileItemWriter<Subrogation> delegate) {
this.delegate = delegate;
}
public FlatFileItemWriter<Subrogation> getDelegate() {
return delegate;
}
/*#Override
public void open(ExecutionContext executionContext)
throws ItemStreamException {
this.delegate.open(executionContext);
}
#Override
public void update(ExecutionContext executionContext)
throws ItemStreamException {
this.delegate.update(executionContext);
}
#Override
public void close() throws ItemStreamException {
this.delegate.close();
}*/
#Override
public void writeHeader(Writer writer) throws IOException {
// TODO Auto-generated method stub
System.out.println("inside header");
writer.write(SubrogationFileTransferTasklet.header);
}
#Override
public void writeFooter(Writer writer) throws IOException {
// TODO Auto-generated method stub
System.out.println("inside header");
String trailer = SubrogationFileTransferTasklet.trailer;
String s1 = StringUtils.substring(trailer, 0, 23);
System.out.println("trailer without contwer is" + s1);
System.out.println("whole traileer is" + s1
+ SubrogationProcessor.totalRecords);
System.out
.println("duplicate data is" + SubrogationProcessor.duplicate);
writer.write(s1 + SubrogationProcessor.totalRecords);
System.out.println("inside Footer");
writer.write("Total Number of Records :: \n\n");
}
/*public void write(List<? extends Subrogation> subrogation) throws Exception {
System.out.println("inside writer");
delegate.write(subrogation);
}*/
}
pls help....
You have two exceptions here. The first one is due to the fact that the type for com.hcsc.ccsp.nonadj.subrogation.writer.SubrogationHeaderFooterWriter.delegate does not match the FlatFileItemWriter. What type is that defined as (if you can update your post with the code for this class, it would be helpful)?
The second one is because you are attempting to use a decider that is step scoped. In a regular Spring Batch job (not a JSR-352 based job), a decider is not a step. Because of that, it doesn't get a StepExecution, and therefore step scope is not supported.
Update
Change your setter for the delegate to take ItemWriter (the interface) instead of FlatFileItemWriter (the implementation) to address the first issue.

Categories