I'm trying to get the build's failed message in nant.onfailure. I Know that I can use try/ catch but I'd like to avoid this route. Is it possible get the failed message without try/catch?
I am not sure if you are aware for NAntContrib library.
http://nantcontrib.sourceforge.net/
You can include their library to get extra sets of 'Tasks'. I am current using task called "record" to do the logging upon success and failure without any try/catch s.
Something like,
<property name="Build.FailureLog" value="C:\TestLog.txt" />
<!-- Start the listener record -->
<record name="${Build.FailureLog}" level="Verbose" action="Start" />
<property name="nant.onfailure" value="Failure" />
<target name="Failure" description="This target is called upon when the build has failed." >
<!-- Close the listener -->
<record name="${Build.FailureLog}" action="Close" />
<!-- Additionally you could send emails by including in mail -->
</target>
Related
I have an sql looks like this.
<sql name="level1">
${alias}some AS ${prefix}some
</sql>
Now I want to nest above fragment into another fragment while propagating those two properties.
<sql name="level2">
${alias}other AS ${prefix}other,
<include refid="level1">
<property name="alias" value="${alias}"/> <!-- will this "${alias}" work? -->
<property name="prefix" value="${prefix}"/> <!-- will this "${prefix}" work? -->
</include>
</sql>
My apologies, I should've tried for myself and saw what happened. But I'm working on a remote site and the testing environment is not complete.
We use NAnt to stop the service, replace the files and start it backup.
<echo message="Waiting for Service to stop."/>
<property name="stopWait" value="360" />
<call target="stopServiceWait" />
... which calls below block
<!--Waits specified number of seconds or until service is stopped.-->
<target name="stopServiceWait">
<if test="${int::parse(stopWait) > 0}">
<echo message="Stopping Service... Waiting ${stopWait} more seconds..."/>
<property name="stopWait" value="${int::parse(stopWait) - 1}" />
<property name="isStopped" value="${service::is-stopped(bf.serviceName, bf.serverName)}" />
<echo message="isStopped - ${isStopped}"/>
<if test="${isStopped == 'False'}">
<sleep seconds="1" />
<echo message="Service is still not stopped"/>
<call target="stopServiceWait" />
</if>
</if>
</target>
However after stopping the service the process often continues running for quite a few seconds, blocking the files. So we just wait some more time right now:
<!--Wait another 60 sec.-->
<echo message="Sleeping additional 60 seconds to ensure that process shuts down after stop."/>
<sleep seconds="60" />
Often long wait is not necessary and just extends outage, or sometimes it is not enough and the deployment has to be restarted.
Question:
Is there a way to check from NANT if the process with the certain name exists?
My use case is simple. I want to handle an exception caused by a system being unreachable, perform a retry based upon a configured retry policy, send an email when the retry threshold has been met, and return a custom response back the caller.
The challenges I am facing is that I cannot both send an email and return a response back to the caller. Since I was using a int-mail:outbound-channel-adapter initially, I would expect this behavior since this is a one-way component:
<int:chain input-channel="defaultErrorChannel">
<int:service-activator id="mailMessageActivator" expression="#mailHandler.process(payload)" />
<int-mail:outbound-channel-adapter mail-sender="mailSender" />
</int:chain>
However, if I introduce a int-amqp:outbound-gateway in front of the int-mail:outbound-channel-adapter (see the Error Handling config below), I would expect to be able to invoke a int:service-activator to construct and return a response to the caller.
Am I thinking about this the wrong way? I see that someone else had a similar question which is still unanswered. Both of the configurations I mentioned send emails, but always block from the caller without receiving a response upon timeout.
Here are the relevant parts of my configuration:
Gateway
<int:gateway id="customerGateway" service-interface="com.uscs.crm.integration.CustomerGateway"
default-request-channel="syncCustomers" default-reply-channel="replySyncCustomers" default-reply-timeout="30000">
</int:gateway>
<int:object-to-json-transformer input-channel="syncCustomers" output-channel="outboundRequestChannel" />
<int-http:outbound-gateway request-channel="outboundRequestChannel" reply-channel="replySyncCustomers"
url="http://voorhees148.uscold.com:9595/web/customerSync/createCustomer"
http-method="POST"
rest-template="restTemplate"
expected-response-type="com.uscs.crm.model.CustSyncResponseVO"
mapped-request-headers="Authorization, HTTP_REQUEST_HEADERS">
<int-http:request-handler-advice-chain>
<ref bean="retryWithBackoffAdviceSession" />
</int-http:request-handler-advice-chain>
</int-http:outbound-gateway>
Error Handling
<int:channel id="defaultErrorChannel"/>
<int:channel id="errorResponses"/>
<!--
ExponentialBackOffPolicy.multipler is applied to wait time over each retry attempt
with a ExponentialBackOffPolicy.maximum configured.
-->
<bean id="retryWithBackoffAdviceSession" class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice">
<property name="retryTemplate">
<bean class="org.springframework.retry.support.RetryTemplate">
<property name="backOffPolicy">
<bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
<property name="initialInterval" value="2000" />
<property name="multiplier" value="2" />
<property name="maxInterval" value="30000"/>
</bean>
</property>
<property name="retryPolicy">
<bean class="org.springframework.retry.policy.SimpleRetryPolicy">
<property name="maxAttempts" value="3"/>
</bean>
</property>
</bean>
</property>
<property name="recoveryCallback">
<bean class="org.springframework.integration.handler.advice.ErrorMessageSendingRecoverer">
<constructor-arg ref="defaultErrorChannel"/>
</bean>
</property>
</bean>
<bean id="custSyncResponseHandler" class="com.uscs.crm.integration.handler.CustSyncResponseHandler"></bean>
<int:chain input-channel="defaultErrorChannel" output-channel="replySyncCustomers">
<int:service-activator id="mailMessageActivator" expression="#mailHandler.process(payload)" />
<int:header-enricher>
<int:header name="ERROR_ID" expression="T(java.lang.System).currentTimeMillis()"/>
</int:header-enricher>
<int-amqp:outbound-gateway
exchange-name="error-responses-exchange"
routing-key-expression="'error.response.'+headers.ERROR_ID"
amqp-template="amqpTemplate" />
<!-- Will this service-activator return a response to the caller (int:gateway) using channel `replySyncCustomers`? -->
<int:service-activator id="custSyncResponseActivator" expression="#custSyncResponseHandler.process(payload)" />
</int:chain>
<int-amqp:inbound-gateway queue-names="error-responses" request-channel="errorResponses"
connection-factory="rabbitConnectionFactory" acknowledge-mode="AUTO" />
<int-mail:outbound-channel-adapter channel="errorResponses" mail-sender="mailSender" />
<!-- (Outbound Channel Adapter/Gateway) rabbit exchanges, queues, and bindings used by this app -->
<rabbit:topic-exchange name="error-responses-exchange" auto-delete="false" durable="true">
<rabbit:bindings>
<rabbit:binding queue="error-responses" pattern="error.response.*"/>
</rabbit:bindings>
</rabbit:topic-exchange>
<rabbit:queue name="error-responses" auto-delete="false" durable="true"/>
SOLUTION: I was able to get this working with help from #Artem. Below are the changes I made.
Service Activator Implementation (handling ErrorMessage)
The key is the line which returns the reconstructed Message with all of the header information from the ErrorMessage.
#Override
public Message<CustSyncResponseVO> process(Message<MessagingException> errorMessage) {
MessagingException errorException = errorMessage.getPayload();
CustSyncResponseVO custSyncResponse = new CustSyncResponseVO();
custSyncResponse.setResponseMessage(ExceptionUtils
.convertToString(errorMessage.getPayload()));
return MessageBuilder.withPayload(custSyncResponse)
.copyHeaders(errorMessage.getHeaders())
.copyHeadersIfAbsent(errorException.getFailedMessage().getHeaders()).build();
}
Service Activator Config
Used SpEL to reference the #root context to retrieve the ErrorMessage instead of the default which would be MessagingException (payload) and passed it to my process method on the POJO.
<bean id="custSyncResponseHandler" class="com.uscs.crm.integration.handler.CustSyncResponseHandler" />
<int:chain id="errorGatewayResponseChain" input-channel="defaultErrorChannel" output-channel="replySyncCustomers">
<int:service-activator id="custSyncResponseActivator" expression="#custSyncResponseHandler.process(#root)" />
</int:chain>
I don't see reason to introduce the AMQP middleware complexity there just for sending email in the end.
What only you need is <publish-subscribe-channel id="defaultErrorChannel"> with to endpoints as subscribers to it.
The first one is one-way email sending <chain> and the second one is custSyncResponseActivator to reply something to your <int-http:outbound-gateway>.
You can find more info on the matter in the Spring Integration Reference Manual.
This involves using a JSR job, so I do not have access to use the tasklet definition in the job specification. The direction I've been given is to support only JSR 352 features as far as job specification goes.
Here is an example of a job:
<job id="xmlWriter" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
<step id="firstStep">
<chunk item-count="2">
<reader ref="DelimitedFlatFileReader">
<properties>
<!-- Reads in from file Test.csv -->
<property name="fileNameAndPath" value="#{jobParameters['readerFileNameAndPath']}" />
<property name="fieldNames" value="firstName, lastName, city" />
<property name="fullyQualifiedTargetClass" value="com.test.test.DatabaseMember" />
</properties>
</reader>
<processor ref="com.test.test.ItemProcessor" />
<writer ref="FlatFileWriter" >
<properties>
<property name="appendOn" value="true" />
<!-- Read to file demoXMLReaderFlatFileWriterOutput.txt -->
<property name="fileNameAndPath" value="#{jobParameters['writerFileNameAndPath']}" />
<property name="fullyQualifiedTargetClass" value="com.test.test.DatabaseMember" />
</properties>
</writer>
</chunk>
</step>
In the ItemProcessor I am interested in having some type of callback/listener that could trigger roll back for transactional items that occur inside it should the chunck for example fail during the write step.
So a good example would be I have some sort of db or jms operation that occurs in the ItemProcessor. If during the writer portion that chunck fails I would want to roll back all of those operations that occurred during the item processor that were part of this iteration (or several with item count > 1).
I have looked into the various listeners available based on the jsr spec and nothing seems to allow for this type of implementation. Also spring does not seem to wrap the processor in a transaction like it does when it is a true spring batch. Testing I did in creating db connections and testing them to see if they were transactional aware always returned false.
Is what I'm looking for even possible outside a entirely custom implementation and if so any guidance in how to accomplish it.
I am trying to integrate IBMMQ v6.0.2 with jbossESB.
we have local Queue available on IBMMQ on one of our QA QUEUEMANAGER.
I am able to listen to the QUEUE using JMSprovider of jboss ESB. As soon as a message (of type jms_text ) is dropped , esb listen to it and pick it up and before it hit the next action it throws following error message.
ERROR [JmsComposer] Unsupported JMS message type: com.ibm.jms.JMSTextMessage
Here are the steps I followed.
jboss-service.mxl : Defined Connection Factory and QUEUE
added jars ( com.ibm.mq.* ) to ${jbossesb}/server/${mynode}/lib
Added jms lsinterner configuration on jboss-esb.xml
Please guide me what I m missing here... Do I need to create custom MessagePlugin ?
jboss-esb looks like this
<jms-provider name="WSMQ" connection-factory="MQQueueConnectionFactory">
<jms-bus busid="queuestartGwChannel"> <jms-message-filter
dest-type="QUEUE"
dest-name="wsmq/SerivceOrderQueue"
acknowledge-mode ="AUTO_ACKNOWLEDGE"
/>
</jms-bus>
<jms-bus busid="queuestartEsbChannel">
<jms-message-filter
dest-type="QUEUE"
dest-name="wsmq/SerivceOrderQueue"
/>
</jms-bus>
</jms-provider>
jboss-service.xml looks like this
<mbean code="jmx.service.wsmq.WSMQConnectionFactory"
name="jmx.service.wsmq:service=MQQueueConnectionFactory">
<attribute name="JndiName">MQQueueConnectionFactory</attribute>
<attribute name="JMSStyle">Queue</attribute>
<attribute name="IsXA">false</attribute>
<attribute name="QueueManagerName">SQAT0083</attribute>
<attribute name="HostName">111.111.111.111</attribute>
<attribute name="Port">1415</attribute>
<attribute name="Channel">MYCO.SVRCONN</attribute>
<attribute name="TransportType">CLIENT</attribute>
<depends>jboss:service=Naming</depends>
</mbean>
<mbean code="jmx.service.wsmq.WSMQDestination"
name="jmx.service.wsmq:service=WSMQRequestQueue">
<attribute name="JndiName">wsmq/SerivceOrderQueue</attribute>
<attribute name="JMSStyle">Queue</attribute>
<attribute name="QueueManagerName">SQAT0083</attribute>
<attribute name="DestinationName">MYCO.SERVICEORDER.QA01.QL01</attribute>
<attribute name="TargetClient">MQ</attribute>
<depends>jboss:service=Naming</depends>
</mbean>
I am using jboss-eap-4.3. Really appreciate any help.
Here is my Service Tag Looks like in jboss-esb.xml
<listeners>
<jms-listener name="MQ-Gateway"
busidref="queuestartGwChannel"
is-gateway="true" maxThreads="1"
/>
<jms-listener name="MQ-EsbListener" busidref="queuestartEsbChannel" />
</listeners>
<actions mep="OneWay">
<action name="serviceOrderMarshaller"
class="com.my.esb.actions.ServiceOrderMessageUnMarshallerAction"
process="unmarshalPayload">
<property name="springContextXml" value="spring/mainApplicationContext.xml"/>
</action>
<action name="serviceOrderStaging"
class="com.my.esb.actions.ServiceOrdersStagingAction"
process="stageServiceOrders">
<property name="springContextXml" value="spring/mainApplicationContext.xml"/>
</action>
<action name="marginAndLeadTimeRetriever"
class="com.my.esb.actions.MarginAndLeadTimeRetrieverAction"
process="retrieveJobCodeInfo">
<property name="springContextXml" value="spring/mainApplicationContext.xml"/>
</action>
<action name="createDraftRequestMapper"
class="com.my.esb.actions.CreateDraftRequestMapperAction"
process="mapData">
<property name="springContextXml" value="spring/mainApplicationContext.xml"/>
</action>
<action name="omsCreateDraftRequestTranslator"
class="com.my.esb.actions.OMSCreateDraftRequestTranslatorAction"
process="translateData">
<property name="springContextXml" value="spring/mainApplicationContext.xml"/>
</action>
<action name="createDraftRequestProcessor"
class="com.my.esb.actions.CreateDraftRequestProcessorAction"
process="dispatchRequest">
<property name="springContextXml" value="spring/mainApplicationContext.xml"/>
</action>
</actions>
Bit late response but if someone reads this, the answer is:
queuestartEsbChannel is listening to the same queue that is delivering jmstextmessages and it has is-gateway set to false (default value).
If is-gateway is false, only ESB messages can be recieved on that listener.
I would have expected to see com.ibm.mqjms.jar in the CLASSPATH for a JMS app, not com.ibm.mq.*.
Depending on the version of WMQ you are using, please reference the Environment Variables page in the Infocenter. WMQ V6 page is here (see Table #2), and the WMQ v7 page is here (see the table and the notes below). Note that the classes have been repackaged between versions and the CLASSPATH requirements are quite different.
On UNIX flavors, you can run the setmqjms script to configure the environment for WMQ JMS. It lives in /opt/mqm/java/bin or /usr/mqm/java/bin on AIX. This assumes a standard WMQ client installation, though. If you just grabbed the jars and relocated them, it won't work. In particular, if you just grabbed the com.ibm.mq* jars it likely won't work. You can verify your installation by running the Initial Verification Test (IVT) supplied with the client install. The additional benefit of using a full WMQ client is that all of the trace utilities and sample code and other diagnostics are installed.
One other piece of advice, be sure to use the WMQ v7 client even if the WMQ server is at v6. This is because WMQ v6 is going out of service next year and will not be supported after that. Using the v7 client now will save you a migration later, CLASSPATH changes, etc. In addition, the v7 classes have lots of cool new features when used with a v7 QMgr such as automatic client reconnection to the same or different QMgr, depending on your configuration. The WMQ client install is a free download (registration required) as SupportPac MQC7.