Problems with Spring WS Streaming Attachments with Security Interceptor - streaming

I'm having problems getting Spring WS to receive a request which has a file attached and use streaming. The problem is I get the following exception whenever I try to use a security interceptor:
2011-01-11 15:10:05,132 DEBUG [org.springframework.ws.soap.server.SoapMessageDispatcher] -
java.lang.IllegalArgumentException: Error in converting SOAP Envelope to Document
at org.springframework.ws.soap.axiom.support.AxiomUtils.toDocument(AxiomUtils.java:135)
at org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor.toDocument(Wss4jSecurityInterceptor.java:621)
at org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor.validateMessage(Wss4jSecurityInterceptor.java:492)
at org.springframework.ws.soap.security.AbstractWsSecurityInterceptor.handleRequest(AbstractWsSecurityInterceptor.java:104)
at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:213)
at org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:168)
at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:88)
at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:57)
at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:230)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:530)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:426)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:457)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:229)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:931)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:361)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:186)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:867)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:245)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:113)
at org.eclipse.jetty.server.Server.handle(Server.java:337)
at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:581)
at org.eclipse.jetty.server.HttpConnection$RequestHandler.content(HttpConnection.java:1020)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:775)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:228)
at org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:417)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:474)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:437)
at java.lang.Thread.run(Thread.java:595)
Caused by: org.apache.axiom.om.OMException: java.util.NoSuchElementException
at org.apache.axiom.om.impl.builder.StAXOMBuilder.next(StAXOMBuilder.java:249)
at org.apache.axiom.om.impl.llom.OMNodeImpl.build(OMNodeImpl.java:327)
at org.apache.axiom.om.impl.llom.OMElementImpl.build(OMElementImpl.java:706)
at org.springframework.ws.soap.axiom.support.AxiomUtils.toDocument(AxiomUtils.java:125)
... 34 more
Caused by: java.util.NoSuchElementException
at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1083)
at org.apache.axiom.om.impl.builder.StAXOMBuilder.parserNext(StAXOMBuilder.java:506)
at org.apache.axiom.om.impl.builder.StAXOMBuilder.next(StAXOMBuilder.java:161)
... 37 more
I am using the Axiom Message Factory:
<bean id="messageFactory" class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory">
<property name="payloadCaching" value="false"/>
<property name="attachmentCaching" value="true"/>
<property name="attachmentCacheThreshold" value="1024" />
</bean>
My endpoint mapping uses the wss4jSecurityInterceptor:
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
<property name="mappings">
<props>
<prop key="{http://www.aquilauk.co.uk/hribulkupload}BulkHRRequest">hriBulkUploadEndpoint</prop>
</props>
</property>
<property name="interceptors">
<list>
<!-- <bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"/> -->
<ref bean="wss4jSecurityInterceptor"/>
</list>
</property>
</bean>
and my security interceptor has been set up to ensure it does not make use of the Payload:
<bean id="wss4jSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
<property name="validationActions" value="UsernameToken" />
<property name="validationCallbackHandler" ref="springWSS4JHandler"/>
<property name="secureResponse" value="false"/>
<property name="secureRequest" value="false" />
</bean>
<bean id="acegiWSS4JHandler"
class="org.springframework.ws.soap.security.wss4j.callback.SpringPlainTextPasswordValidationCallbackHandler">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
Regard,
Craig

I believe that the security interceptor you have defined still consumes the payload. It just doesn't perform any security validation on it. The AxiomSoapMessageFactory.createWebServiceMesssage() method should be being called in order to create the MessageContext that is provided to the security interceptor. The security interceptor then ignores it as per the secureRequest flag.

I Found the solutions to this problem through trial and error:
The problem is the setup of the wss4jSecurityInterceptor, the lines:
<property name="secureResponse" value="false"/>
<property name="secureRequest" value="false" />
should have been:
<property name="validateRequest" value="false" />
<property name="validateResponse" value="false" />

Related

AffinityKeyMapped not working with Ignite 2.4/2.5/2.6 and Scala

Using Scala 2.11.7/Java 1.8.0_161/RHEL7.
We have two caches whose elements share the same affinity key. The affinity key is defined as follows:
case class IgniteTradePayloadKey(
#(AffinityKeyMapped#field)
tradeKey: TradeKey,
... other fields
) extends Serializable
case class IgniteDealPayloadKey(
#(AffinityKeyMapped#field)
tradeKey: TradeKey,
child: Int,
... other fields
) extends Serializable
Those are used as key to two ignite caches (Trades and Deals). We want instances of Trades and Deals to be collocated, as we perform computations using both. Think of them as having a parent/child relationship, and we would like to keep the parent and its children in the same node because our calculations require both. Parents are uniquely identified by TradeKey, so we use that in both caches to control affinity. Note that they are also used as part of the Ignite key itself. They are not part of the value.
This worked beautifully with Ignite 1.7; we then tried to upgrade to a more recent version of Ignite (we tried 2.4, 2.5 and 2.6), and without any code change whatsoever, there are children that are no longer collocated with their parents. Reverted back to 1.7 to be sure, and collocation works. We tried to override the affinity function with something simple (just a hash on the TradeKey), and again, it works with 1.7, but not with any of the 2.X versions listed above.
What are we missing?
Configuration as requested (apologies for the massive file). We tried with and without defining our own affinity function, with the same results.
<beans xmlns="http://www.springframework.org/schema/beans"
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_FALLBACK"/>
<property name="searchSystemEnvironment" value="true"/>
</bean>
<bean id="CLIENT_MODE" class="java.lang.String">
<constructor-arg value="${IGNITE_CLIENT_MODE:false}" />
</bean>
<!-- Ignite common configuration -->
<bean abstract="true" id="common.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="gridName" value="MTS Trades Cache Grid" />
<property name="failureDetectionTimeout" value="60000"/>
<property name="clientFailureDetectionTimeout" value="60000"/>
<property name="peerClassLoadingEnabled" value="true"/>
<property name="clientMode" ref="CLIENT_MODE"/>
<property name="rebalanceThreadPoolSize" value="4"/>
<property name="deploymentMode" value="CONTINUOUS"/>
<property name="discoverySpi">
<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
<property name="localPort" value="47700"/>
<property name="localPortRange" value="20"/>
<!-- Setting up IP finder for this cluster -->
<property name="ipFinder">
<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
<property name="addresses">
<list>
<value>127.0.0.1:47700..47720</value>
</list>
</property>
</bean>
</property>
</bean>
</property>
<property name="communicationSpi">
<bean class="org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi">
<property name="localPort" value="49100"/>
<property name="sharedMemoryPort" value="-1" />
<property name="messageQueueLimit" value="1024"/>
</bean>
</property>
<!-- Cache configuration -->
<property name="cacheConfiguration">
<list>
<!-- deals -->
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="dealPayloads" />
<property name="cacheMode" value="PARTITIONED" />
<property name="backups" value="0" />
<property name="OnheapCacheEnabled" value="true"/>
<property name="queryEntities">
<list>
<bean class="org.apache.ignite.cache.QueryEntity">
<!-- setting indexed type's key class -->
<property name="keyType" value="com.company.ignite.IgniteDealPayloadKey" />
<!-- setting indexed type's value class -->
<property name="valueType" value="com.company.ignite.IgniteDealPayload" />
</bean>
</list>
</property>
<property name="affinity">
<bean class="com.company.ignite.affinity.IgniteAffinityFunction">
<property name="partitions" value="1024"/>
</bean>
</property>
<property name="atomicityMode" value="ATOMIC" />
<property name="rebalanceMode" value="ASYNC" />
<property name="copyOnRead" value="false" />
<!-- Set rebalance batch size to 8 MB. -->
<property name="rebalanceBatchSize" value="#{8 * 1024 * 1024}"/>
<!-- Explicitly disable rebalance throttling. -->
<property name="rebalanceThrottle" value="0"/>
<!-- Set 4 threads for rebalancing. -->
<property name="rebalanceThreadPoolSize" value="4"/>
</bean>
<!-- trade versions -->
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="tradePayloads" />
<property name="cacheMode" value="PARTITIONED" />
<property name="backups" value="0" />
<property name="OnheapCacheEnabled" value="true"/>
<property name="queryEntities">
<list>
<bean class="org.apache.ignite.cache.QueryEntity">
<!-- setting indexed type's key class -->
<property name="keyType" value="com.company.ignite.IgniteTradePayloadKey" />
<!-- setting indexed type's value class -->
<property name="valueType" value="com.company.ignite.IgniteTradePayload" />
</bean>
</list>
</property>
<property name="affinity">
<bean class="com.company.ignite.affinity.IgniteAffinityFunction">
<property name="partitions" value="1024"/>
</bean>
</property>
<property name="atomicityMode" value="ATOMIC" />
<property name="rebalanceMode" value="ASYNC" />
<property name="copyOnRead" value="false" />
<!-- Set rebalance batch size to 8 MB. -->
<property name="rebalanceBatchSize" value="#{8 * 1024 * 1024}"/>
<!-- Explicitly disable rebalance throttling. -->
<property name="rebalanceThrottle" value="0"/>
<!-- Set 4 threads for rebalancing. -->
<property name="rebalanceThreadPoolSize" value="4"/>
</bean>
</list>
</property>
</bean>
</beans>
In addition, this is the relevant exception:
[22:28:24,418][INFO][grid-timeout-worker-#23%MTS Trades Cache Grid%][IgniteKernal%MTS Trades Cache Grid] FreeList [name=MTS Trades Cache Grid, buckets=256, dataPages=9658, reusePages=0]
[22:28:57,335][INFO][pub-#314%MTS Trades Cache Grid%][GridDeploymentLocalStore] Class locally deployed: class com.company.pt.tradesrouter.routing.ComputeJob
[22:28:57,705][SEVERE][pub-#314%MTS Trades Cache Grid%][GridJobWorker] Failed to execute job [jobId=48df049c461-b3ba568d-6a39-4296-b03f-0c046e7cf3f7, ses=GridJobSessionImpl [ses=GridTaskSessionImpl [taskName=com.company.pt.tradesrouter.routing.ComputeJob, dep=GridDeployment [ts=1532382444003, depMode=CONTINUOUS, clsLdr=sun.misc.Launcher$AppClassLoader#764c12b6, clsLdrId=a717c19c461-e5241c47-40d4-4085-a7fa-4f1916275b2e, userVer=0, loc=true, sampleClsName=o.a.i.i.processors.cache.distributed.dht.preloader.GridDhtPartitionFullMap, pendingUndeploy=false, undeployed=false, usage=2], taskClsName=com.company.pt.tradesrouter.routing.ComputeJob, sesId=38df049c461-b3ba568d-6a39-4296-b03f-0c046e7cf3f7, startTime=1532384937062, endTime=1532388537300, taskNodeId=b3ba568d-6a39-4296-b03f-0c046e7cf3f7, clsLdr=sun.misc.Launcher$AppClassLoader#764c12b6, closed=false, cpSpi=null, failSpi=null, loadSpi=null, usage=1, fullSup=false, internal=false, topPred=null, subjId=b3ba568d-6a39-4296-b03f-0c046e7cf3f7, mapFut=IgniteFuture [orig=GridFutureAdapter [ignoreInterrupts=false, state=INIT, res=null, hash=1635946755]], execName=null], jobId=48df049c461-b3ba568d-6a39-4296-b03f-0c046e7cf3f7]]
class org.apache.ignite.IgniteException: null
at org.apache.ignite.internal.processors.closure.GridClosureProcessor$C2.execute(GridClosureProcessor.java:1858)
at org.apache.ignite.internal.processors.job.GridJobWorker$2.call(GridJobWorker.java:566)
at org.apache.ignite.internal.util.IgniteUtils.wrapThreadLoader(IgniteUtils.java:6623)
at org.apache.ignite.internal.processors.job.GridJobWorker.execute0(GridJobWorker.java:560)
at org.apache.ignite.internal.processors.job.GridJobWorker.body(GridJobWorker.java:489)
at org.apache.ignite.internal.util.worker.GridWorker.run(GridWorker.java:110)
at org.apache.ignite.internal.processors.job.GridJobProcessor.processJobExecuteRequest(GridJobProcessor.java:1189)
at org.apache.ignite.internal.processors.job.GridJobProcessor$JobExecutionListener.onMessage(GridJobProcessor.java:1921)
at org.apache.ignite.internal.managers.communication.GridIoManager.invokeListener(GridIoManager.java:1555)
at org.apache.ignite.internal.managers.communication.GridIoManager.processRegularMessage0(GridIoManager.java:1183)
at org.apache.ignite.internal.managers.communication.GridIoManager.access$4200(GridIoManager.java:126)
at org.apache.ignite.internal.managers.communication.GridIoManager$9.run(GridIoManager.java:1090)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
at com.company.pt.tradesrouter.routing.ComputeJob$$anonfun$1$$anonfun$2.apply(ComputeJob.scala:49)
at com.company.pt.tradesrouter.routing.ComputeJob$$anonfun$1$$anonfun$2.apply(ComputeJob.scala:47)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.immutable.Set$Set1.foreach(Set.scala:79)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)
at scala.collection.AbstractSet.scala$collection$SetLike$$super$map(Set.scala:47)
at scala.collection.SetLike$class.map(SetLike.scala:92)
at scala.collection.AbstractSet.map(Set.scala:47)
at com.company.pt.tradesrouter.routing.ComputeJob$$anonfun$1.apply(ComputeJob.scala:47)
at com.company.pt.tradesrouter.routing.ComputeJob$$anonfun$1.apply(ComputeJob.scala:44)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.immutable.HashMap$HashMap1.foreach(HashMap.scala:221)
at scala.collection.immutable.HashMap$HashTrieMap.foreach(HashMap.scala:428)
at scala.collection.immutable.HashMap$HashTrieMap.foreach(HashMap.scala:428)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)
at scala.collection.AbstractTraversable.map(Traversable.scala:104)
at com.company.pt.tradesrouter.routing.ComputeJob.call(ComputeJob.scala:44)
at com.company.pt.tradesrouter.routing.ComputeJob.call(ComputeJob.scala:21)
at org.apache.ignite.internal.processors.closure.GridClosureProcessor$C2.execute(GridClosureProcessor.java:1855)
... 14 more
Most probably, you hit a bug, that was introduced in Ignite 2.0: https://issues.apache.org/jira/browse/IGNITE-5795
Because of this bug #AffinityKeyMapped annotation is ignored in classes, that are used in query entity configuration. As far as I can see, this is exactly your case.
It's going to be fixed in Ignite 2.7.
There is a workaround for this problem: you can list the problematic classes in BinaryConfiguration#classNames configuration property. Binary configuration should be specified as IgniteConfiguration#binaryConfiguration. This configuration should be the same on all nodes. You may also need to configure CacheConfiguration#keyConfiguration for your cache.

Spring Batch : Field or property 'stepExecutionContext' cannot be found

I have the following spring batch job configuration. There is a single reader which then passes details to a composite writer which has two specific writers. Both writers share a common parent and need to use the same JobId for the INSERT operations they execute.
<bean id="job" parent="simpleJob">
<property name="steps">
<list>
<bean parent="simpleStep">
<property name="itemReader" ref="policyReader"/>
<property name="itemWriter" ref="stagingCompositeWriter"/>
</bean>
</list>
</property>
</bean>
<bean id="stagingCompositeWriter" class="org.springframework.batch.item.support.CompositeItemWriter">
<property name="delegates">
<list>
<ref bean="stagingLoadWriter"/>
<ref bean="stagingPolicyWriter"/>
</list>
</property>
</bean>
<bean id="abstractStagingWriter" class="a.b.c.AbstractStagingWriter" abstract="true">
<property name="stepExecution" value="#{stepExecutionContext}"/>
<property name="hedgingStagingDataSource" ref="hedgingStagingDataSource"/>
</bean>
<bean id="stagingLoadWriter" class="a.b.c.StagingLoadWriter" parent="abstractStagingWriter"/>
<bean id="stagingPolicyWriter" class="a.b.c.StagingPolicyWriter" parent="abstractStagingWriter"/>
When i run my code i get the following error
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property 'stepExecutionContext' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext'
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:208)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:72)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:93)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:88)
at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:139)
I have tried setting the scope="step" in various place but to no avail. Any suggestions?
You can access the stepExecutionContext only within a bean defined in the scope="step".
Change your bean definition to
<bean id="stagingLoadWriter" scope="step" class="a.b.c.StagingLoadWriter" parent="abstractStagingWriter" />
<bean id="stagingPolicyWriter" scope="step" class="a.b.c.StagingPolicyWriter" parent="abstractStagingWriter"/>

In-memory Job-Explorer definition in Spring batch

I was trying to share My in-memory jobRepository to the jobExplorer. But it throws an error as,
Nested exception is
org.springframework.beans.ConversionNotSupportedException:
Failed to convert property value of type '$Proxy1 implementing
org.springframework.batch.core.repository.JobRepository,org.
springframework.aop.SpringProxy,org.springframework.aop.framework.Advised'
to required type
Even i tried putting '&' sign before jobRepository when passing to jobExplorer for sharing.But attempt end in vain.
I am using Spring Batch 2.2.1
Is the dependency for jobExplorer is only database not in-memory?
Definition is,
<bean id="jobRepository"
class="com.test.repository.BatchRepositoryFactoryBean">
<property name="cache" ref="cache" />
<property name="transactionManager" ref="transactionManager" />
</bean>
<bean id="jobOperator" class="test.batch.LauncherTest.TestBatchOperator">
<property name="jobExplorer" ref="jobExplorer" />
<property name="jobRepository" ref="jobRepository" />
<property name="jobRegistry" ref="jobRegistry" />
<property name="jobLauncher" ref="jobLauncher" />
</bean>
<bean id="jobExplorer" class="test.batch.LauncherTest.TestBatchExplorerFactoryBean">
<property name="repositoryFactory" ref="&jobRepository" />
</bean>
<bean id="transactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="jobLauncher" class="com.scb.smartbatch.core.BatchLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<!-- To store Batch details -->
<bean id="jobRegistry" class="com.scb.smartbatch.repository.SmartBatchRegistry" />
<bean id="jobRegistryBeanPostProcessor"
class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
<property name="jobRegistry" ref="jobRegistry" />
</bean>
<!--Runtime cache of batch executions -->
<bean id="cache" class="com.scb.cache.TCRuntimeCache" />
thanks for your valuable inputs.
But I used '&' before the job repository reference, which allowed me to use it for my job explorer as a shared resource.
problem solved.
kudos.
Usually you have to wire interface instead of implementation.
Else, probably, you have to add <aop:config proxy-target-class="true"> to create CGLIB-based proxy instead of standard Java-based proxy.
Read Spring official documentation about that

Spring RESTful web service Unmapped URI Exception Handling

I am developing a simple spring REST web service. From the research I did there could be two types of 404 exceptions.
For example,
#Controller
#RequestMapping("/person")
#Transactional(readOnly=true)
public class PersonController {
#RequestMapping(value="/data", method={RequestMethod.GET,RequestMethod.POST})
#ResponseStatus(value=HttpStatus.OK)
public Person getPerson() {
return service.getPerson();
}
}
Type 1: http://localhost/myws/person/get will throw a 404 from web service.
Type 2: http://localhost/myws/idontexist will throw a 404 from web server container. In my case it is tomcat.
To handle, Type 1, I tried extending DefaultHandlerExceptionResolver and overriding handleNoSuchRequestHandlingMethod
To handle Type 2, I added the below snippet in my web.xml<error-page>
<error-code>404</error-code>
<location>/WEB-INF/pages/notfound.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/WEB-INF/pages/notfound.jsp</location>
</error-page>
My servlet xml looks like,
<context:component-scan base-package="com" />
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="ignoreAcceptHeader" value="true" />
<property name="order" value="1" />
<property name="contentNegotiationManager">
<bean class="org.springframework.web.accept.ContentNegotiationManager">
<constructor-arg>
<bean class="org.springframework.web.accept.ParameterContentNegotiationStrategy">
<constructor-arg>
<map>
<entry key="json" value="application/json"/>
<entry key="xml" value="application/xml"/>
</map>
</constructor-arg>
</bean>
</constructor-arg>
</bean>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="autodetectAnnotations" value="true"/>
</bean>
</constructor-arg>
</bean>
</list>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="order" value="2" />
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<!--To handle Internal Server Errors -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver">
<property name="order" value="1"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver" >
<property name="order" value="2"/>
</bean>
<!--RestExceptionHandler extends DefaultHandlerExceptionResolver -->
<bean class="com.rest.exception.RestExceptionHandler">
<property name="order" value="3"/>
</bean>
<!-- data source and Daos...-->
When I hit the Type 2 URL, I am getting the below Exception.
WARN org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/myws/WEB-INF/pages/notfound.jsp] in DispatcherServlet with name 'restservlet'
But my JSP is present in the mentioned location. What could be the problem?
This is what I did. I created a controller to handle 404 instead of JSP as I couldn't get the problem with JSPs. It works as expected.

How to initialize ConnectionFactory for remote JMS queue when remote machine is not running?

Using JBoss 4.0.5, JBossMQ, and Spring 2.0.8, I am trying to configure Spring to instantiate beans which depend on a remote JMS Queue resource. All of the examples I've come across depend on using JNDI to do lookup for things like the remote ConnectionFactory object.
My problem is when trying to bring up a machine which would put messages into the remote queue, if the remote machine is not up, JNDI lookup simply fails, causing deployment to fail. Is there a way to get Spring to keep trying to lookup this object in the background while not blocking the remainder of deployment?
Iit's difficult to be sure without seeing your spring config, but assuming you're using Spring's JndiObjectFactoryBean to do the JNDI lookup, then you can set the lookupOnStartup property to false, which allows the context to start up even if the JNDI target isn't there. The JNDI resolution will be done the first time the ConnectionFactory is used.
However, this just shifts the problem further up the chain, because if some other component tries to get a JMS Connection on startup, then you're back where you started. You can use the lazy-init="true" attribute on your other beans to prevent this from happening on deployment, but it's easy to accidentally put something in your config which forces everything to initialize.
You're absolutely right. I tried setting lookupOnStartup to false and lazy-init=true . This just defers the problem to the first time that the Queue is attempted to be used. Then an exception as follows is thrown:
[org.jboss.mq.il.uil2.SocketManager] Failed to handle: org.jboss.mq.il.uil2.msgs.CloseMsg29702787[msgType: m_connectionClosing, msgID: -2147483606, error: null]
java.io.IOException: Client is not connected
Moreover, it looks like the lookup is never attempted again. When the machine with the remote queue is brought back up, no messages are ever processed subsequently. This really does seem like it should be well within the envelope of use cases for J2EE nonsense, and yet I'm not having much luck... It feels like it should even maybe be a solved problem.
For completion's sake, the following is the pertinent portion of my Spring configuration.
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.provider.url">localhost:1099</prop>
<prop key="java.naming.factory.url.pkgs">org.jnp.interfaces:org.jboss.naming</prop>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
</props>
</property>
</bean>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>ConnectionFactory</value>
</property>
</bean>
<bean id="remoteJndiTemplate" class="org.springframework.jndi.JndiTemplate" lazy-init="true">
<property name="environment">
<props>
<prop key="java.naming.provider.url">jnp://10.0.100.232:1099</prop>
<prop key="java.naming.factory.url.pkgs">org.jnp.interfaces:org.jboss.naming</prop>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
</props>
</property>
</bean>
<bean id="remoteConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true">
<property name="jndiTemplate" ref="remoteJndiTemplate"/>
<property name="jndiName" value="ConnectionFactory" />
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.ConnectionFactory" />
</bean>
<bean id="destinationResolver" class="com.foo.jms.FooDestinationResolver" />
<bean id="localVoicemailTranscodingDestination" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate"/>
<property name="jndiName" value="queue/voicemailTranscoding" />
</bean>
<bean id="globalVoicemailTranscodingDestination" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true" >
<property name="jndiTemplate" ref="remoteJndiTemplate" />
<property name="jndiName" value="queue/globalVoicemailTranscoding" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate" >
<property name="connectionFactory" ref="connectionFactory"/>
<property name="defaultDestination" ref="localVoicemailTranscodingDestination" />
</bean>
<bean id="remoteJmsTemplate" class="org.springframework.jms.core.JmsTemplate" lazy-init="true">
<property name="connectionFactory" ref="remoteConnectionFactory"/>
<property name="destinationResolver" ref="destinationResolver"/>
</bean>
<bean id="globalQueueStatus" class="com.foo.bar.recording.GlobalQueueStatus" />
<!-- Do not deploy this bean for machines other than transcoding machine -->
<condbean:cond test="${transcoding.server}">
<bean id="voicemailMDPListener"
class="org.springframework.jms.listener.adapter.MessageListenerAdapter" lazy-init="true">
<constructor-arg>
<bean class="com.foo.bar.recording.mdp.VoicemailMDP" lazy-init="true">
<property name="manager" ref="vmMgr" />
</bean>
</constructor-arg>
</bean>
</condbean:cond>
<bean id="voicemailForwardingMDPListener"
class="org.springframework.jms.listener.adapter.MessageListenerAdapter" lazy-init="true">
<constructor-arg>
<bean class="com.foo.bar.recording.mdp.QueueForwardingMDP" lazy-init="true">
<property name="queueStatus" ref="globalQueueStatus" />
<property name="template" ref="remoteJmsTemplate" />
<property name="remoteDestination" ref="globalVoicemailTranscodingDestination" />
</bean>
</constructor-arg>
</bean>
<bean id="prototypeListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer"
abstract="true"
lazy-init="true">
<property name="concurrentConsumers" value="5" />
<property name="connectionFactory" ref="connectionFactory" />
<!-- 2 is CLIENT_ACKNOWLEDGE: http://java.sun.com/j2ee/1.4/docs/api/constant-values.html#javax.jms.Session.CLIENT_ACKNOWLEDGE -->
<!-- 1 is autoacknowldge -->
<property name="sessionAcknowledgeMode" value="1" />
<property name="sessionTransacted" value="true" />
</bean>
<!-- Do not deploy this bean for machines other than transcoding machine -->
<condbean:cond test="${transcoding.server}">
<bean id="voicemailMDPContainer" parent="prototypeListenerContainer" lazy-init="true">
<property name="destination" ref="globalVoicemailTranscodingDestination" />
<property name="messageListener" ref="voicemailMDPListener" />
</bean>
</condbean:cond>
<bean id="voicemailForwardMDPContainer" parent="prototypeListenerContainer" lazy-init="true">
<property name="destination" ref="localVoicemailTranscodingDestination" />
<property name="messageListener" ref="voicemailForwardingMDPListener" />
</bean>