How to use updateItem to update read and flag proerties at the same time - exchangewebservices

For developing mail functions to access exchange server, I use API of 'UpdateItem' to update mails' read&flag properties, send xml request as below,
but the server returned response with error of 'a:ErrorInvalidRequest'.
How can I update the item's read&flag properties by using 'UpdateItem' in one request?
'UpdateItem' API: https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateitem-operation
<t:ItemChange>
<t:ItemId Id="AAMkADE06AAA=" />
<t:Updates>
<t:SetItemField>
<t:FieldURI FieldURI="message:IsRead" />
<t:Message>
<t:IsRead>false</t:IsRead>
</t:Message>
</t:SetItemField>
<t:SetItemField>
<t:FieldURI FieldURI="item:Flag" />
<t:Message>
<t:Flag>
<t:FlagStatus>false</t:FlagStatus>
</t:Flag>
</t:Message>
</t:SetItemField>
</t:Updates>
</t:ItemChange>

I find the cause, I have made a mistake in the flag part of my xml request, can't use 'false', but need to use 'NotFlagged' .
I should write as below, it will works well
<t:SetItemField>
<t:FieldURI FieldURI="item:Flag" />
<t:Message>
<t:Flag>
<t:FlagStatus>NotFlagged</t:FlagStatus>
</t:Flag>
</t:Message>
</t:SetItemField>

Related

Azure Api Manager cache-remove-value policy not removing the cache item

I am caching certain values in my azure api manager policy and in certain cases remove the item to clean up the cache and retrieve the value back from the api.
Based on my experience, even after I remove the value using the cache-remove-value policy, my next api call still finds the value in the cache. Here is a sample code:
<cache-store-value key="Key123" value="123" duration="300" />
<cache-lookup-value key="Key123" variable-name="CacheVariable" />
<cache-remove-value key="Key123" />
<cache-lookup-value key="Key123" default-value="empty" variable-name="CacheVariable2" />
<return-response>
<set-status code="504" reason="" />
<set-body>#(context.Variables.GetValueOrDefault<string>("CacheVariable2"))</set-body>
</return-response>
This code basically returns empty or "123" in the body based on if the cache item with key Key123 was found after being removed or not. This always returns the value of the cached item, "123".
Did anyone experienced this issue or found a way to clean up the cache?
If I continously check in a Retry, I can see that the item is sometimes cleaned after 2 seconds, sometimes 1 minute. I think the delete call is an async or queued call in the background so that we can't really be sure if it's cleaned or not without continuously checking.
UPDATE:
As an actual solution for now, instead of deleting, I actually update the cache item with 1 second duration and a dirty value.
This happens because cache removal request is asynchronous in regards to request processing pipeline, i.e. APIM does not wait for cache item to be removed before continuing with request, thus it is possible to still retrieve it right after removal request since it has not been sent yet.
Updated based on your scenario: why don't you try something like this then:
<policies>
<inbound>
<base />
</inbound>
<backend>
<retry condition="#(context.Response.StatusCode == 200)" count="10" interval="1">
<choose>
<when condition="#(context.Variables.GetValueOrDefault("calledOnce", false))">
<send-request mode="new" response-variable-name="response">
<set-url>https://EXTERNAL-SERVICE-URL</set-url>
<set-method>GET</set-method>
</send-request>
<cache-store-value key="externalResponse" value="EXPRESSION-TO-EXTRACT-DATA" duration="300" />
<!--... or even store whole response ...-->
<cache-store-value key="externalResponse" value="#((IResponse)context.Variables["response"])" duration="300" />
</when>
<otherwise>
<cache-lookup-value key="externalResponse" variable-name="externalResponse" />
<choose>
<when condition="#(context.Variables.ContainsKey("externalResponse"))">
<!-- Do something with cached data -->
</when>
<otherwise>
<!-- Call extenal service and store in cache again -->
</otherwise>
</choose>
<set-variable name="calledOnce" value="#(true)" />
</otherwise>
</choose>
<forward-request />
</retry>
</backend>
<outbound>
<base />
</outbound>

Same Appender log into 2 different files with Log4J2

I would like to define 1 single Appender in my log4j2.xml configuration file, and using the magic of the Properties Substitution of Log4J2, be able to somehow log into 2 different files.
I imagine the Appender would look something like:
<RollingFile name="Rolling-${filename}" fileName="${filename}" filePattern="${filename}.%i.log.gz">
<PatternLayout>
<pattern>%d %p %c{1.} [%t] %m%n</pattern>
</PatternLayout>
<SizeBasedTriggeringPolicy size="500" />
</RollingFile>
Is there a way for a Logger to use this appender and to pass the filename property?
Or is there a way to pass it when we fetch the Logger with LogManager.getLogger?
Note that those logger may or may not be in the same Thread, it has to support both cases, so I don't think it's possible to use ThreadContext nor System properties.
The closest thing I can think of is RoutingAppender. RoutingAppender allows the log file to be dynamically selected based on values in some lookup. A popular built-in lookup is the ThreadContext map (see the example on the FAQ page), but you can create a custom lookup. Example code:
ThreadContext.put("ROUTINGKEY", "foo");
logger.debug("This message gets sent to route foo");
// Do some work, including logging by various loggers.
// All logging done in this thread is sent to foo.
// Other threads can also log to foo at the same time by setting ROUTINGKEY=foo.
logger.debug("... and we are done");
ThreadContext.remove("ROUTINGKEY"); // this thread no longer logs to foo
Example config that creates log files on the fly:
<Routing name="Routing">
<Routes pattern="$${ctx:ROUTINGKEY}">
<!-- This route is chosen if ThreadContext has a value for ROUTINGKEY.
The value dynamically determines the name of the log file. -->
<Route>
<RollingFile name="Rolling-${ctx:ROUTINGKEY}" fileName="logs/other-${ctx:ROUTINGKEY}.log"
filePattern="./logs/${date:yyyy-MM}/${ctx:ROUTINGKEY}-other-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout>
<pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="6" modulate="true" />
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
</RollingFile>
</Route>
</Routes>
<!-- This route is chosen if ThreadContext has no value for key ROUTINGKEY. -->
<Route key="$${ctx:ROUTINGKEY}">
<RollingFile name="Rolling-default" fileName="logs/default.log"
filePattern="./logs/${date:yyyy-MM}/default-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout>
<pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="6" modulate="true" />
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
</RollingFile>
</Route>
</Routing>
An alternative is to configure multiple loggers, each pointing to a separate appender (with additivity="false"). This allows your application to control the destination file by obtaining a logger by its name. However, in that case you would need to configure separate appenders so this does not fulfill your requirement, I mention it for completeness.
I am using the logger name to pass arguments to the appender.
It's hacky but it works:
LogManager.getLogger("com.company.test.Test.logto.xyz.log")
A custom StrLookup is necessary to extract the filename from the logger name.

Exchange Web Service listing items of a folder

I am getting this error message from MS Exchange:
The EWS Id is in EwsLegacyId format which is not supported by the Exchange version specified by your request. Please use the ConvertId method to convert the Id from EwsId to EwsLegacyId format.
in response to the following soap request:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
</soap:Header>
<soap:Body>
<m:FindItem Traversal="Shallow">
<m:ItemShape>
<t:BaseShape>Default</t:BaseShape>
<!--
<t:AdditionalProperties>
<t:FieldURI FieldURI="item:TextBody" />
<t:FieldURI FieldURI="item:Body" />
</t:AdditionalProperties>
-->
</m:ItemShape>
<m:IndexedPageItemView MaxEntriesReturned="100" Offset="0" BasePoint="Beginning" />
<m:ParentFolderIds>
<t:FolderId Id="AQMkAGEzZTIzOWNmLWFiMGUtNDg5NC05NzNlLTUxN2FmNGQ3ZjIxMQAALgAAA95uXloT2IJPlNaCGuwj8ycBAObfRJ+1FF9PkWpl8+aNmhoAAAIBDAAAAA==" ChangeKey="AQAAABYAAADm30SftRRfT5FqZfPmjZoaAAAPjzNZ" />
</m:ParentFolderIds>
</m:FindItem>
</soap:Body>
I got the folder id from a previous FindFolder operation which list the folder hierarchy.
How to solve this problem?
I too had same problem.
Added the RequestServerVersion in the Header. That solved the problem.
' <soap:Header>' +
' <RequestServerVersion Version="Exchange2013" xmlns="http://schemas.microsoft.com/exchange/services/2006/types" soap:mustUnderstand="0" />' +
' </soap:Header>' +
You need to add
<t:RequestServerVersion Version="Exchange2007_SP1" />
between your tags. Version can be any of those defined here: EWS schema versions in Exchange.
However, once you get that past that error you'll get another one for trying to request the item:TextBody and item:Body. To get the body of a message, you'll need to send a GetItem operation that includes the ItemId of the item to bind to (ie. get).
See this page for more info: How to: Work with Exchange mailbox items by using EWS.

Number of lines read with Spring Batch ItemReader

I am using SpringBatch to write a csv-file to the database. This works just fine.
I am using a FlatFileItemReader and a custom ItemWriter. I am using no processor.
The import takes quite some time and on the UI you don't see any progress. I implemented a progress bar and got some global properties where i can store some information (like lines to read or current import index).
My question is: How can i get the number of lines from the csv?
Here's my xml:
<batch:job id="importPersonsJob" job-repository="jobRepository">
<batch:step id="importPersonStep">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="personItemReader"
writer="personItemWriter"
commit-interval="5"
skip-limit="10">
<batch:skippable-exception-classes>
<batch:include class="java.lang.Throwable"/>
</batch:skippable-exception-classes>
</batch:chunk>
<batch:listeners>
<batch:listener ref="skipListener"/>
<batch:listener ref="chunkListener"/>
</batch:listeners>
</batch:tasklet>
</batch:step>
<batch:listeners>
<batch:listener ref="authenticationJobListener"/>
<batch:listener ref="afterJobListener"/>
</batch:listeners>
</batch:job>
I already tried to use the ItemReadListener Interface, but this isn't possible as well.
if you need to know how many lines where read, it's available in spring batch itself,
take a look at the StepExecution
The method getReadCount() should give you the number you are looking for.
You need to add a step execution listener to your step in your xml configuration. To do that (copy/pasted from spring documentation):
<step id="step1">
<tasklet>
<chunk reader="reader" writer="writer" commit-interval="10"/>
<listeners>
<listener ref="chunkListener"/>
</listeners>
</tasklet>
</step>
where "chunkListner" is a bean of yours annotated with a method annotated with #AfterStep to tell spring batch to call it after your step.
you should take a look at the spring reference for step configuration
Hope that helps,

Amazon Product API: "Your request is missing a required parameter combination" on Blended ItemSearch

I'm having some problems trying to do an ItemSearch on the Blended index using the Amazon Product API.
According to the documentation, Blended requests cannot specify the MerchantId parameter - and indeed, if I try to include it I get an error telling me so. However, when I don't include it, I get an error telling me that my request is missing a required parameter combination and that a valid combination includes MerchantId... what the hell?
The failing requests are being sent as part of batches with other requests that are succeeding. I'm using REST to send my requests, so here's an example:
http://ecs.amazonaws.com/onca/xml?AWSAccessKeyId=-------------&
ItemSearch.1.Keywords=Mates%20of%20State&
ItemSearch.1.MerchantId=Amazon&
ItemSearch.1.SearchIndex=DVD&
ItemSearch.2.Keywords=teaching%20Lily%20various%20computer%20related%20skills&
ItemSearch.2.SearchIndex=Blended&
ItemSearch.Shared.Availability=Available&
ItemSearch.Shared.Condition=All&
ItemSearch.Shared.ResponseGroup=Small%2CSalesRank%2CImages%2COfferSummary%2CSimilarities&
Operation=ItemSearch%2CSimilarityLookup&
Service=AWSECommerceService&
SimilarityLookup.1.ItemId=B000FNNHZ2&
SimilarityLookup.2.ItemId=B000EQ5UPU&
SimilarityLookup.Shared.Availability=Available&
SimilarityLookup.Shared.Condition=All&
SimilarityLookup.Shared.MerchantId=Amazon&
SimilarityLookup.Shared.ResponseGroup=Small%2CSalesRank%2CImages%2COfferSummary&
Timestamp=2010-04-02T17%3A18%3A05Z&
Signature=----------------
Here's the XML response:
<Items xmlns="http://webservices.amazon.com/AWSECommerceService/2005-10-05">
<Request>
<IsValid>False</IsValid>
<ItemSearchRequest>
<Availability>Available</Availability>
<Condition>All</Condition>
<Keywords>teaching Lily various computer related skills</Keywords>
<ResponseGroup>Similarities</ResponseGroup>
<ResponseGroup>SalesRank</ResponseGroup>
<ResponseGroup>OfferSummary</ResponseGroup>
<ResponseGroup>Small</ResponseGroup>
<ResponseGroup>Images</ResponseGroup>
<SearchIndex>Blended</SearchIndex>
</ItemSearchRequest>
<Errors>
<Error>
<Code>AWS.MissingParameterCombination</Code>
<Message>Your request is missing a required parameter combination. Required parameter combinations include MerchantId, Availability.</Message>
</Error>
</Errors>
</Request>
</Items>
Any ideas as to what I'm doing wrong?
I seem to have solved this by removing both the Availability and Condition parameters. I'd ideally prefer to be able to filter by availability, but at least it's working.