I have a program that contains some for-loops. The idea of the program is to log into a website using multiple accounts and retrieve a list (each login brings a different list). So the way I have it setup is with an enhanced for loop:
loginsList.put( "firstUsername", "firstPassword" );
loginsList.put( "secondUsername", "secondPassword" );
loginsList.put( "thirdUsername", "thirdPassword" );
loginsList.put( "fourthUsername", "fourthPassword" );
loginsList.put( "fifthUsername", "fifthPassword" );
for ( Entry<String, String> nextLogin : logins.entrySet() ) {
String nextUser = nextLogin.getKey();
String nextPass = nextLogin.getValue();
Response authenticateUserResponse = Jsoup.connect( WEBSITE_I_NEED_TO_LOGIN_TO )
.data( "username", nextUser )
.data( "password", nextPass )
.execute();
Basically here is what i want the flow to be:
read()--> obtain list----> send list to write() method to write it to the database--> loop back around and get the next login-->read()--> obtain list-->send it to the write()....etc..
however the issue I'm having is that my loop runs in the read method and does not go to the write method until all the lists have been traversed in all the accounts. Essentially the write is only being called once at the end, so what I have right now is something like this(this is the flawed design):
read()--->obtain list-->next account--->obtain list---next account--->obtain list--->write()
How can I organize the chunk processing in Spring to write after I read a chunk only?
for ( Entry<String, String> nextLogin : logins.entrySet() ) {
String nextUser = nextLogin.getKey();
String nextPass = nextLogin.getValue();
//do something
......
//call write function
writeValues(x, y, z);
}
Is this all you want?
Otherwise it seems like a traditional SpringBatch: Read > Process > Proceeed case.
You will have your reader = gets a record
Procesor > saves a record
Spring batch moves you to next record if the was no error.
<step id="processUpdates">
<tasklet task-executor="batchThreadPoolTaskExecutor" throttle-limit="${batch.cviscoreupdate.threadcount}">
<chunk reader="Reader" processor="ItemProcessor" writer="ItemWriter" commit-interval="${batch.commit.interval}" skip-limit="${batch.skip.limit}" >
<skippable-exception-classes>
<include class="batch.support.SkipRecordException" />
</skippable-exception-classes>
</chunk>
</tasklet>
<next on="FAILED" to="errorExit"/>
<next on="*" to="moveFilesFromWorkToDone" />
<listeners>
<listener ref="UpdateSkipListener"/>
</listeners>
</step>
<bean id="CVIScoreUpdateItemProcessor" class="com.batch.MyUpdateItemProcessor" scope="step" init-method="init" />
Related
I'm using Apache Camel 2.17 and using the simple language to catch a null exchange. It is not working and I've tried several formatting approaches, but it doesn't catch a null. I believe it is the format/syntax of how I'm using it. please instruct where I'm going wrong. thank you!
<process id="_process18" ref="csvMarshallerProcessor"/>
<process id="toReOrgCSV" ref="reOrgCSVData"/>
<choice id="_choice13">
<when id="_when13">
<simple>"${body}" == null</simple>
<log id="_log22" message="body is NULL, do not send NULL body!"/>
<stop id="_stop7"/>
</when>
<otherwise id="_otherwise1">
I've tried
<simple>"${body} == null"</simple>
<simple>"${body}" == null</simple>
<simple>${body} == null</simple>
<simple>${body} == 'null'</simple>
I set the exchange to null in a previous process IF the data is filtered out and ineligiable to send out. I'd like to just use Camel Spring XML.
???
Don't set the exchange as null, as that is not valid, set the message body to null or empty string etc.
exchange.getIn().setBody(null);
And then you can use simple to test its null,
${body} == null
Or if you set it as empty text
${body} == ''
thank you Claus!
this is what I ended up with, ..
...
line.append(System.lineSeparator());
if ( lookup ) {
if ( validate(fleetName, line.toString()) ) {
baos.write(line.toString().getBytes());
}
} else {
baos.write(line.toString().getBytes());
}
}
List<String> serviceRecords = new ArrayList<String>(Arrays.asList(baos.toString().split(System.lineSeparator())));
if ( serviceRecords.size() > 1 ) { //has more than a header
byte[] ba = baos.toByteArray();
exchange.getIn().setBody(ba);
} else {
exchange.getIn().setBody(null); //empty message, only header, no data
}
Camel Context
<process id="_process18" ref="csvMarshallerProcessor"/>
<choice id="_choice13">
<when id="_when13">
<simple trim="true">"${body}" == "" || ${body} == null</simple>
<log id="_log22" message="body is NULL, do not send NULL body!"/>
<stop id="_stop7"/>
</when>
<otherwise id="_otherwise1">
<process id="toReOrgCSV" ref="reOrgCSVData"/>
<to id="_to7" uri="{{DDFEndpoint}}?fileName={{APMLoaderPath}}/${header.aircraftMetadata.shipNumber}-${header.enginePosition}_${header.messageDateTime}.csv"/>
<log id="_log23" message="Sending data packet: ${header.aircraftMetadata.outputPath}/${header.aircraftMetadata.shipNumber}-${header.enginePosition}_${header.messageDateTime}.csv"/>
</otherwise>
</choice>
</aggregate>
In my rapidclipse 4.0 project, I have to read data out of a database view, while saving manual entered data.
The readed value should then be included into the data to be saved.
My problem is, that this works fine, only onetime/ the first save.
If I save a second time, the value is not updated.
In the save-button click event I placed following code:
private void cmdSave_buttonClick(final Button.ClickEvent event) {
try {
this.txtDmvTable.setValue("T_supplier");
final int i = 1;
VSuppliersNewId vsni = new VSuppliersNewId();
vsni = new VSuppliersNewIdDAO().find(i);
this.txtDmvCol00.setValue(vsni.getNewSupId().toString());
this.fieldGroup.save();
}
catch(final Exception e) {
e.printStackTrace();
Notification.show("Do isch was falsch",
e.getMessage(),
Notification.Type.ERROR_MESSAGE);
}
}
The following lines did exactly what expected, but only one time:
final int i = 1;
VSuppliersNewId vsni = new VSuppliersNewId();
vsni = new VSuppliersNewIdDAO().find(i);
this.txtDmvCol00.setValue(vsni.getNewSupId().toString());
The view VSuppliersNewId will always give back only one uptodate value.
For example:
My view gives back the highest value out of a table field.
Lets asume in the first round it gives back the number 237
After saving my data, the view will give back perhaps 238
If I read this direct by sql in the database I get back 238
but by the above code it still persists the 237
I assume, that the whole code chain from database has to be refreshed/ reloaded, but it didn't.
How to change/enhance my code to get the expected result? What did I wrong?
I found the solution by myself
There are several steps which I did.
1) opend my entity and set cacheable = false
2) opend persistence.xml and set following parameters:
<property name="hibernate.cache.use_query_cache" value="false" />
<property name="xdev.queryCache.mode" value="ENABLE_SELECTIVE" />
<property name="hibernate.cache.use_second_level_cache" value="false" />
I used following code to get the table refresh done:
private void cmdSave_buttonClick(final Button.ClickEvent event) {
try
{
this.txtDmvTable.setValue("T_supplier");
final int i = 1;
PersistenceUtils.getEntityManager(manOKMContacts.class).unwrap(SessionFactory.class);
VSuppliersNewId vsni = new VSuppliersNewId();
vsni = new VSuppliersNewIdDAO().find(i);
this.txtDmvCol00.clear();
this.txtDmvCol00.setValue(vsni.getNewSupId().toString());
this.fieldGroup.save();
this.table.getBeanContainerDataSource().removeAll();
this.table.getBeanContainerDataSource().addAll(new OkmDbMetadataValueDAO().findAllContacts());
this.table.getBeanContainerDataSource().refresh();
this.table.setSortContainerPropertyId("DmvCol00");
this.table.sort();
}
catch(final Exception e)
{
Notification.show("Do isch was falsch", e.getMessage(), Notification.Type.ERROR_MESSAGE);
}
}
Hope this will help others
If I have two separate mule flows that would run synchronously
<flow name="GatherDDICollection" doc:name= "GatherDDICollection" processingStrategy="synchronous" >
<poll doc:name= "Poll" frequency ="5000">
<invoke object-ref="numberInformationCollectionFlow" method="popWaiting" doc:name="PopPending"/>
</poll>
<expression-filter expression="#[payload != null && ((payload instanceof org. mule.transport. NullPayload) == false) && payload.size() > 0 ]" doc:name ="HasRequest"/>
<logger message= "Collection request - #[payload]" level= "INFO" doc:name="Logger" />
</flow >
<flow name= "ProvisionDDI" doc:name ="ProvisionDDI" processingStrategy="synchronous" >
<poll doc:name="Poll" frequency="5000" >
<invoke object-ref="numberInformationCollectionFlow" method="getParentDdis" doc:name= "DataToProvision"/>
</poll>
<expression-filter expression="#[payload != null && ((payload instanceof org. mule.transport. NullPayload) == false) && payload > 0]" doc:name="HasDataToProvision" />
<logger message= "DDI to provision- #[payload]" level="INFO" doc:name= "Logger"/>
</flow >
Would the payload get confused which flow it belongs to?
I ask because I am confuse with the current scenario:
The first flow (GatherDDICollection) will not show "Collection request -.." because method "popWaiting" returns null.
The second flow (ProvisionDDI) should show "DDI to provision .." because te method "getParentDdis" returns a list of objects but it doesn't (I know this because if I remove the expression-filter on the second flow, the logger shows the message . Is this because it is getting confused with the payload from the first flow?
I'm building an application where I have mainDoc which can have one or more related notes Documents. In the mainDoc there is a repeat control that is bound to Payments.getAllItems(WFSMainDoc.getValue("LinkKey")); The java class Payments has methods that manipulate and ArrayList of PaymentItems. The getAllItems method grabs all of the related NotesDocuments and loads them into an ArrayList. If the ArrayList already exists it just returns the previously built ArrayList. The button in the Repeat sets viewScope.vsRIndex = rIndex; and viewScope.vsShowPayment = true; which now displays the panelPaymentDetail and the custom control that has a custom property of type java.lang.Object and load pItem using pItem = Payments.getItem(rIndex); return pItem;
all of the above works and I have a couple sample controls below. I have two issues:
1. The compositeData.pItem is computed over and over again and as far as I can tell keeps returning the original values from the Payments.getAllItems() even though I'm editing them in the payment input 'form' -- the question then is how can I block this repeated calculation?
The save button in the Payment Input custom control does not appear to fire (none of the print statements occur when clicked) I think the reloading of the Object pItem gets in the way.
Test Main Document Control:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.data>
<xp:dominoDocument var="WFSMainDoc" formName="frmMainDoc"
computeWithForm="onsave" ignoreRequestParams="false">
<xp:this.documentId><![CDATA[${javascript:var UNID:String = sessionScope.get("ssUNID");
(UNID == null || UNID == "") ? "" : UNID}]]></xp:this.documentId>
<xp:this.action><![CDATA[${javascript:if (sessionScope.containsKey("ssUNID")){
if(sessionScope.get('ssUNID').length){
sessionScope.get('ssAction') == 'edit' ? 'editDocument':'openDocument'
} else {
return 'createDocument'
break;
}
}else{
return "createDocument";
break;
}}]]></xp:this.action>
<xp:this.databaseName><![CDATA[${appProps[sessionScope.ssApplication].appFilePath}]]></xp:this.databaseName>
</xp:dominoDocument>
</xp:this.data>
Main document
<xp:br></xp:br>
<xp:inputText id="inputText1" value="#{WFSMainDoc.LinkKey}"
defaultValue="#{javascript:#Unique}">
</xp:inputText>
<xp:br></xp:br>
Other Fields and controls
<xp:br></xp:br>
<xp:panel id="panelPaymentContainer">
<xp:repeat id="repeatData" rows="10" var="pItem"
indexVar="rIndex">
<xp:this.value><![CDATA[#{javascript:Payments.getAllItems(WFSMainDoc.getValue("LinkKey"));}]]></xp:this.value>
<xp:button id="buttonEditPayment"
rendered="#{javascript:(WFSMainDoc.isEditable())}">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="panelPaymentsContainer">
<xp:this.action><![CDATA[#{javascript:try{
viewScope.vsRIndex = rIndex;
viewScope.vsShowPayment = true;
break;
}catch(e){
WFSUtils.sysOut("Error in calling dialogPayment " + e.tostring)
}}]]>
</xp:this.action>
</xp:eventHandler>
</xp:button>
<br />
</xp:repeat>
<xp:panel id="panelPaymentInput">
<xp:this.styleClass><![CDATA[#{javascript:(viewScope.vsShowPayment) ? "" : "display=none";}]]></xp:this.styleClass>
<xc:ccTestPaymentInput rendered="#{javascript:(viewScope.vsShowPayment)}">
<xc:this.pItem><![CDATA[#{javascript:try{
var debug:Boolean = true;
if (debug) WFSUtils.sysOut("Open existing row = " + viewScope.vsRIndex)
rIndex = parseInt(viewScope.vsRIndex.toString());
if (debug) WFSUtils.sysOut("rIndex = " + rIndex);
pItem = Payments.getItem(rIndex);
return pItem;
}catch(e){
WFSUtils.sysOut("Failure in Custom Prop of add item " + e.toString());
return null;
}}]]></xc:this.pItem>
</xc:ccTestPaymentInput>
</xp:panel>
</xp:panel><!-- panelPaymentContainer -->
<xp:br></xp:br>
<xp:br></xp:br>
</xp:view>
payment Input Control
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:br></xp:br>
Actual Pay Date:
<xp:inputText id="actualPayDate"
value="#{compositeData.pItem.actualPayDate}">
<xp:dateTimeHelper id="dateTimeHelper1"></xp:dateTimeHelper>
<xp:this.converter>
<xp:convertDateTime type="date"></xp:convertDateTime>
</xp:this.converter>
</xp:inputText>
<br /> <br />
<xp:button value="Save" id="button1">
<xp:eventHandler event="onclick"
submit="true" refreshMode="partial" refreshId="panelPayments">
<xp:this.action><![CDATA[#{javascript:try{
var debug:Boolean = true;
if (debug) print("Start Payment save");
var pos:Integer = parseInt(viewScope.vsRIndex.toString());
if (debug) print("Working with pos = " + pos + " Call saveThisItem");
if (Payments.saveThisItem(compositeData.pItem , pos)){
if (debug) print("save Payments Worked ");
}else{
if (debug) print("save Payments FAILED ");
}
}catch(e){
print("payment save Error " + e.tostring);
}finally{
viewScope.vsExpPayDate = "";
viewScope.remove("vsShowPayment");
viewScope.remove("vsRIndex");
viewScope.remove("vsGotItem")
}}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:view>
This is all very complicated, and I'm far from understanding what you're trying to achieve here. But at least I found a few oddities in your code:
ad 1: there is a panel with id="panelPaymentContainer" containing a repeat. Inside that repeat is a button doing a partialRefresh on an id="panelPaymentsContainer" >> is this a typo (plural vs. singular forms in "Payment(s))? Should the button be refreshing the panel?
Assuming that this assumption is true: every time you click the button the panel is refreshed together with all its contents, thus also refreshing the repeat's datasource. And so pItem will always be pushed from "outside in" into the content of your repeat. - If the refreshId thing is NOT a typo, then what should it be? I tried hard to read the entire code, but there's a lot of it, so I might have missed something
ad 2: similar thing here: the save button tries to refresh something with an id="panelPayments", but I cannot see anything with this id. So no wonder it doesn't appear to do anything useful.
My recommendation for complicated tasks like these: try to strip everything down to the bare essentials; the more complicated your code is the harder it is to find its mistakes. Start with a panel, a repeat and a few simple controls like a button and a bunch of computed fields to display some test values. Then as soon as this very simple model is working you can start to add to it. - Simplifying also helps others to find mistakes in you concept, btw.
I try to recover the answer of the user but i can't.
I have a dropdownbutton, I recover the list and the value by default by a java class.
It's ok about this.
But when I try to push another text of the list : nothing append...
<xe:dropDownButton id="dropdownEtatDoc">
<xe:this.treeNodes>
<xe:basicContainerNode>
<!-- Affiche l'état du document par défaut-->
<xe:this.label id="labelEtatDoc">
<![CDATA[#{javascript:
etatDoc.nomEtatDoc;
}]]>
</xe:this.label>
<!-- affiche la liste des états du document-->
<xe:repeatTreeNode var="index" value="#{etatDoc.listEtatDoc}">
<xe:this.children>
<xe:basicLeafNode label="#{index}" submitValue="#{index}" />
</xe:this.children>
</xe:repeatTreeNode>
</xe:basicContainerNode>
</xe:this.treeNodes>
<!-- actualise la chaine sélectionnée-->
<xp:eventHandler event="onItemClick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:
var montest = getComponent("dropdownEtatDoc").submittedValue();
etatDoc.nomEtatDoc = montest;
}]]></xp:this.script>
</xp:executeScript>
</xp:this.action>
</xp:eventHandler>
</xe:dropDownButton>
An idea ? Thanks !
I use a combobox and it's ok, I don't know why...
My code for anyone has the same problem :
<xp:this.beforePageLoad>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:
viewScope.etat = etatDoc.listEtatDoc;
viewScope.grdFam = chapitre.listChapitre1;
}]]></xp:this.script>
</xp:executeScript>
</xp:this.beforePageLoad>
<xp:div>
<!--**************** DEBUT CBXETATDOC *************************************************************-->
<xp:label value="Etat : " id="label1"></xp:label>
<xp:comboBox id="cbxEtat">
<xp:selectItem itemLabel="Tout" itemValue="" />
<xp:selectItems value="#{viewScope.etat}" />
<xp:eventHandler event="onchange" submit="true" refreshMode="complete" immediate="true">
<xp:this.action>
<xp:executeScript>
<xp:this.script>
<![CDATA[#{javascript:
var etat = getComponent("cbxEtat").submittedValue;
}]]>
</xp:this.script>
</xp:executeScript>
</xp:this.action>
</xp:eventHandler>
</xp:comboBox>
Assuming "etatDoc" is a NotesXspDocument and not a bean.
1) If you are having trouble getting the submitted value, get it via the context:
var submitted = context.getSubmittedValue();
print("submitted: " + submitted); //check if it is there, delete afterward
switch(submitted){
case("btn1")
//doSomething(submitted);
break;
}
Since you are using the repeater node, it would not be practical to use the switch for all of it, but you could make a default where you do what ever you need to with the index value.
2) then I do not think you are setting the value properly. Try:
var montest = submitted;
etatDoc.replaceItemValue("nomEtatDoc", etatDoc.getItemValue("nomEtatDoc").add(montest))
//gets the current list (java.util.Vector) from the document
//add a value to the list
//replace the value with the new list
I am assuming that you are not using a self-made-bean for this.