Can't unmarshall REST response Spring-Jibx - java

I have a problem unmarshalling a RESTful request body using Spring and Jibx.
This is the request body I'm sending through Postman:
<?xml version="1.0" encoding="utf-8"?>
<locationRequest xmlns="urn:ietf:params:xml:ns:geopriv:held" responseTime="30000">
<locationType exact="true">
geodetic
civic
locationURI
</locationType>
<device xmlns="urn:ietf:params:xml:ns:geopriv:held:id">
<uri>tel:123456789;phone-context=+1</uri>
</device>
</locationRequest>
This is my binding.xml
...
<mapping name="locationRequest" class="com.example.integrations.models.LocationRequest" ordered="true">
<namespace uri="urn:ietf:params:xml:ns:geopriv:held" default="elements" />
<value name="responseTime" field="responseTime" style="attribute" usage="optional"/>
<structure name="locationType" field="locationType" map-as="locationType" usage="required"/>
<structure field="device" usage="required"/>
</mapping>
<mapping name="device" class="com.example.integrations.models.Device" >
<namespace uri="urn:ietf:params:xml:ns:geopriv:held:id" default="elements" />
<value name="uri" field="uri" />
</mapping>
<mapping abstract="true" type-name="locationType" class="com.example.integrations.models.LocationType">
<value name="exact" field="exact" style="attribute"/>
<value field="types" style="text"
serializer="com.example.integrations.ParseUtil.serializeStringList"
deserializer="com.example.integrations.ParseUtil.deserializeStringList" />
</mapping>
...
When I run the Jibx compiler everything is fine and all classes are detected and modified by the compiler correctly
This is the method that receive the web service call:
The request its unmarshalled correctly if I use a .xml file as the input, but if I go through the web service its missing some data:
...
<locationType exact="true">
geodetic
civic
locationURI
</locationType>
...
The "exact" attribute is parsed correctly, but the content, while on the xml file was parsed ok, is missing in the web service object... and for the love of me I can't figure out why.
(Note: Also the response object (LocationResponse) is not marshalled correctly when returning to Postman)
This is my Spring-servlet configuration relevant to jibx:
...
<beans:bean id="unmarshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
<beans:property name="targetClass" value="org.dellroad.jibxbindings.pidf.held.LocationRequest"/>
<beans:property name="bindingName" value="locationRequest"/>
</beans:bean>
<beans:bean id="marshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
<beans:property name="targetClass" value="org.dellroad.jibxbindings.pidf.held.LocationRequest"/>
<beans:property name="bindingName" value="locationRequest"/>
</beans:bean>
...
What am I missing here? I suspect is a missconfiguration in the Spring side

Related

How to enable addressing feature in cxf xml?

How can I add default WS-addressing to the xml?
<cxf:cxfEndpoint id="endpoint" xmlns:s="http://tempuri.org/"
address="https://uslugaterytws1test.stat.gov.pl/TerytWs1.svc"
endpointName="s:custom"
serviceName="s:TerytWs1"
wsdlURL="classpath:/wsdl/terytws1.wsdl">
<cxf:properties>
<entry key="schema-validation-enabled" value="false" />
</cxf:properties>
<cxf:inInterceptors>
</cxf:inInterceptors>
<cxf:inFaultInterceptors>
</cxf:inFaultInterceptors>
<cxf:outInterceptors>
</cxf:outInterceptors>
<cxf:outFaultInterceptors>
</cxf:outFaultInterceptors>
</cxf:cxfEndpoint>
<cxf:cxfEndpoint id="poxyEndpoint" xmlns:s="http://tempuri.org/"
address="http:localhost:5678/myproxy"
endpointName="s:customProxy"
serviceName="s:TerytWs1Proxy"
wsdlURL="classpath:/wsdl/terytws1Proxy.wsdl">
<cxf:properties>
<entry key="schema-validation-enabled" value="false" />
</cxf:properties>
<cxf:inInterceptors>
</cxf:inInterceptors>
<cxf:inFaultInterceptors>
</cxf:inFaultInterceptors>
<cxf:outInterceptors>
<ref component-id="wssOutInterceptor" />
</cxf:outInterceptors>
<cxf:outFaultInterceptors>
<ref component-id="wssOutInterceptor" />
</cxf:outFaultInterceptors>
</cxf:cxfEndpoint>
<camelContext id="proxyTerytContext" xmlns="http://camel.apache.org/schema/blueprint">
<route id="route-TerytWs1">
<from id="inbound" uri="cxf:bean:proxyEndpoint?dataFormat=CXF_MESSAGE" />
<to id="outbound" uri="cxf:bean:endpoint?dataFormat=CXF_MESSAGE" />
</route>
</camelContext>
When I send request to http:localhost:5678/myproxy then I get:
<faultcode xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:InvalidSecurity</faultcode>
<faultstring xml:lang="en-US">An error occurred when verifying security for the message.</faultstring>
I have read many similar questions and examples but haven't found the solution for pure cxf xml. I have been trying to solve this for 2 days. Now I'm crying.
EDIT:
This is an original wsdl: https://uslugaterytws1test.stat.gov.pl/terytws1.svc?wsdl
and this is my proxy to it: https://github.com/woblak/training/blob/master/teryt_testProxy.wsdl
user: TestPubliczny
pass: 1234abcd
There are some examples in the Camel unit tests which test CXF endpoints with WS-Addressing enabled; WSAddressingTest-context.xml seems like it might be relevant to your question?
Here, WS-Addressing has been enabled on a CXF endpoint by adding the wsa:addressing element in features:
<cxf:cxfEndpoint...>
<cxf:features>
<wsa:addressing xmlns:wsa="http://cxf.apache.org/ws/addressing" />
</cxf:features>
</cxf:cxfEndpoint>
The error seems to be related to security. You have an interceptor configured (wssOutInterceptor) but there's no source code. Perhaps you should look there to see if you're setting the auth details.
I would also add message logging so you can see the content of the payload sent to the target and verify that it contains your credentials.
Or, if you're using the Camel CXF namespace ( xmlns:cxf="http://camel.apache.org/schema/cxf") you can use:
<cxf:cxfEndpoint ... loggingFeatureEnabled="true">
...
</cxf:cxfEndpoint>

How to remove namespace from Jaxb2 generated xml

I have a problem a little problem related to the namespaces in the XML marshalled by Jaxb2 . When I print out the xml file, I get this "extra" annotations on the xml tags. Is there any way to get rid of the extra namespace annotations ?
Here is an example:
<?xml version="1.0" encoding="UTF-8" standalone="yes">
<root xmlns:ns2="http://www.something.com/something">
<ns2:food>steak</ns2:food>
<ns2:beverage>water</ns2:beverage>
</root>
I want to get rid of the ns2: namespace.
I tried with :
<bean id="glsJaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="${gls.jaxb2.contextpath}"/>
<property name="marshallerProperties">
<map>
<entry key="com.sun.xml.bind.namespacePrefixMapper">
<bean class="es.fs.fswarehousing.gls.ws.EmptyNamespacePrefixMapper"/>
</entry>
</map>
</property>
</bean>
But im getting :
ERROR [TaskExecutor-master-555-ProcessTask [8796749431734]]
[ActionNode] Error executing
org.springframework.oxm.UncategorizedMappingException: Unknown JAXB
exception; nested exception is javax.xml.bind.PropertyException: name:
com.sun.xml.bind.namespacePrefixMapper value:
es.fs.fswarehousing.gls.ws.EmptyNamespacePrefixMapper#17f6a8fe
Can someone give me any hint :) ?

How to get Operational Attrs with Spring Ldap Authorization

I'm having difficulties to read some operational attrs from user data coming with ldap authentication in spring. I know there's already bunch of Q&As about this subject but none of em really helped me. What I need is to get isMemberOf attrs. Our company LDAP admin says 'isMemberOf is an operational attr so it doesnt come with the regular ones from the ldap authentication response. Therefore you need to request them by name' and he gave me this shell command he uses for it to give me an idea to get them :
-bash-3.2$ ldapsearch -h XXX -p 10389 -b dc=entp,dc=tgc -e -1 -T -D "uid=XXX,ou=SpecialUsers,dc=entp,dc=tgc" -w XXX uid=XXX ismemberof
dn: uid=XXX,ou=people,o=XXX,dc=entp,dc=tgc
ismemberof: cn=3G01,ou=functionGroups,ou=Groups,dc=entp,dc=tgc
Spring versions in my project :
<spring.version>3.1.1.RELEASE</spring.version>
<spring.security.version>3.1.0.RELEASE</spring.security.version>
<spring.data.commons.version>1.3.1.RELEASE</spring.data.commons.version>
<spring.ldap.version>1.3.1.RELEASE</spring.ldap.version>
.properties file that stores ldap configuration :
app.ldap.url=ldap://XXX
app.ldap.manager.base=uid=XXX,ou=SpecialUsers,dc=entp,dc=tgc
app.ldap.manager.password=XXX
app.ldap.user.base=dc=entp,dc=tgc
app.ldap.user.filter=(uid={0})
app.ldap.user.role.key=ApplicationProfile
Beans definitons for authentication :
<beans>
<s:authentication-manager alias="authenticationManager">
<s:authentication-provider ref="ldapAuthProvider" />
</s:authentication-manager>
<bean id="contextSource"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="${ldap.url}" />
<property name="userDn" value="${ldap.manager.base}" />
<property name="password" value="${ldap.manager.password}" />
</bean>
<bean id="ldapAuthProvider"
class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<constructor-arg ref="bindAuthenticator" />
<constructor-arg ref="authoritiesPopulator" />
<property name="userDetailsContextMapper" ref="userDetailsContextMapper" />
</bean>
<bean id="bindAuthenticator"
class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="contextSource" />
<property name="userSearch" ref="userSearch"/>
</bean>
<bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg value="${ldap.user.base}" />
<constructor-arg value="${ldap.user.filter}" />
<constructor-arg ref="contextSource" />
</bean>
<bean id="authoritiesPopulator"
class="core.spring.security.ldap.AttributeBasedLDAPAuthoritiesPopulator">
<constructor-arg value="${ldap.user.role.key}" />
</bean>
<bean id="userDetailsContextMapper"
class="core.spring.security.ldap.CustomUserDetailsContextMapper" />
</beans>
And when I debug getGrantedAuthorities(DirContextOperations userData, String username) function that populates authorities in my AttributeBasedLDAPAuthoritiesPopulator class, userData only includes these attrs and no other like isMemberOf (XXXs are actually some real data):
birthdate=birthdate: 06/28/1983,
givenname=givenName: Dummy User,
mobile=mobile: XXX,
workflowaccess=WorkflowAccess: 0,
objectclass=objectClass: mdsMVLink, top, person, inetOrgPerson, organizationalPerson, inetUser, inetAdmin, iplanet-am-managed-person, iPlanetPreferences, iplanet-am-user-service,
mdsmvlinktype=mdsMVLinkType: MV#CV1#A,
userpassword=userPassword: XXX,
mdsentityowner=mdsEntityOwner: MV,META,
ou=ou: XXX,
applicationprofile=ApplicationProfile: XXX
uid=uid: XXX,
mail=mail: XXX,
cn=cn: XXX,
managername=managerName: XXX,
manager=manager: uid=XXX,ou=people,o=XXX,dc=entp,dc=tgc,
employeenumber=employeeNumber: TEST15,
functionalgroupname=functionalgroupname: dummy-functionalgroupname,
mdslinktocv=mdsLinkToCV: MV#CV1#uid=DUMMY,ou=Employees,
status=status: 1,
mdsmvmembership=mdsMVMembership: CV1#True,
inetuserstatus=inetUserStatus: Active,
description=description: XXX,
sn=sn: for TEA project,
organization=Organization: XXX
So my question is how can I get isMemberOf attrs too with these ones?
What i've tried so far:
1- Adding another filter in .properties to include ismemberof
app.ldap.user.filter=(&(uid={0})(ismemberof=*))
2- Making isMemberOf the keyword for roles
app.ldap.user.role.key=isMemberOf
3- Tried to get it explicitly from userData in populator class
userData.getObjectAttributes("isMemberOf")
You need to add the attribute ismemberof to the requested attributes of your userSearch bean:
<bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg value="${ldap.user.base}" />
<constructor-arg value="${ldap.user.filter}" />
<constructor-arg ref="contextSource" />
<property name="returningAttributes">
<list>
<value>*</value>
<value>ismemberof</value>
</list>
</property>
</bean>
You need to specify both values (* and ismemberof) because of the behaviour of ldap server:
if you don't specify attribute names, it will return all user attributes
if you specify attribute names, it will return exactly those attribute (whether user attribute or operational attribute)
if you want all user attributes and some operational attributes, you specify * for all user attributes and list all the operational attributes you want

Server inbound redirection can't find a next Restlet

I'm trying to add a simple redirect into a web application built in Restlets, and it's proving non-trivial. The task is a simple one: I want to actually redirect all missing files from a web application to the same static file.
I'm using org.restlet.routing.Redirector with the following values (I'm using Spring injection):
<bean name="router" class="org.restlet.ext.spring.SpringRouter">
<constructor-arg ref="trackerComponentChildContext" />
<property name="attachments">
<map>
<entry key="/api" value-ref="apiRouter" />
<entry key="/statics" value-ref="staticsDirectory" />
<entry key="/" value-ref="staticsRedirector" />
</map>
</property>
</bean>
<bean id="staticsRedirector" class="ca.uhnresearch.pughlab.tracker.restlets.CustomRedirector">
<constructor-arg ref="trackerComponentChildContext" />
<constructor-arg value="{o}/statics/index.html" />
<constructor-arg value="7" />
</bean>
I can play with the file hierarchy relatively simply, but I just want to send anything that doesn't match either /api or /statics to /statics/index.html within the same application.
Restlet is almost getting it, and it does seem now to pick up the reference to the correct file, it just doesn't quite serve it.
I've put a working copy of the whole thing (including Thierry's suggestions below) at: https://github.com/morungos/restlet-spring-static-files. What I'd like to happen is something like the equivalent sequential attempts below:
curl http://localhost:8080/statics/**/* to hit the corresponding /statics/**/*
curl http://localhost:8080 to hit the main /statics/index.html
curl http://localhost:8080/**/* to hit the main /statics/index.html
I made some tests regarding your issue and I can't figure out how to have your message :-(. Perhaps it's because I haven't the whole code.
In fact, I saw a problem at the level of the SpringRouter itself. I would like to attach the redirector with an attachDefault and not an attach("/", ...) / attach("", ...). The method setDefaultAttachment actually does an attach("", ...).
So I made work something with the following updates:
Create a custom SpringRouter
public class CustomSpringRouter extends SpringRouter {
public void setDefaultAttachment(Object route) {
if (route instanceof Redirector) {
this.attachDefault((Restlet) route);
} else {
super.setDefaultAttachment(route);
}
}
}
Create a custom Redirector. I got the context from the component instead of a child context.
public class CustomRedirector extends Redirector {
public CustomRedirector(Component component, String targetPattern, int mode) {
super(component.getContext(), targetPattern, mode);
}
}
I then use the following Spring configuration:
<?xml version="1.0" encoding="UTF-8"?>
<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="myComponent" class="org.restlet.ext.spring.SpringComponent">
<property name="defaultTarget" ref="router" />
</bean>
<bean name="router" class="test.CustomSpringRouter">
<property name="attachments">
<map>
<entry key="/api" value-ref="apiRouter" />
<entry key="/statics" value-ref="staticsDirectory" />
</map>
</property>
<property name="defaultAttachment" ref="staticsRedirector" />
</bean>
<bean id="staticsRedirector" class="test.CustomRedirector">
<constructor-arg ref="myComponent" />
<constructor-arg value="{o}/statics/index.html" />
<constructor-arg value="7" />
</bean>
<bean name="apiRouter" class="org.restlet.ext.spring.SpringRouter">
(...)
</bean>
(...)
</beans>
Hope it helps you,
Thierry

Spring MVC with Spring Webflow

I am trying to use Spring Webflow with my Spring MVC application.I had a look at the booking-mvc example and followed it,but most of the examples on the web are done with Tiles.I Hope that i am not completely wrong in my understanding and that Spring Webflow can be used with Spring MVC
I am trying to use Spring MVC controllers.But when i am doing a transition like submit/finish nothing seems to happen.
Here is my Flow xml:
<view-state id="enterBookingDetails">
<transition on="submit" to="reviewBooking" />
</view-state>
<view-state id="reviewBooking">
<transition on="confirm" to="bookingConfirmed" />
<transition on="revise" to="enterBookingDetails" />
<transition on="cancel" to="bookingCancelled" />
</view-state>
I Have enterBookingDetails and reviewBooking defined as controllers :
#RequestMapping(value = "/enterBookingDetails", method = RequestMethod.GET)
public ModelAndView getPage(final HttpServletRequest request) {
ModelAndView modelView = new ModelAndView();
modelView.setViewName("pa");
return modelView;
}
#RequestMapping(value = "/reviewBooking", method = RequestMethod.GET)
public ModelAndView getPage2(final HttpServletRequest request) {
ModelAndView modelView = new ModelAndView();
modelView.setViewName("pb");
return modelView;
}
My Jsp looks like this :
<form:form>
<input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}" />
<input type="hidden" name="_eventId" value="finished" />
<input type="submit" value="Submit" name="_eventId_finished" />
</form:form>
And finally my configuration :
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="mvcViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
<property name="order" value="1" />
</bean>
<!-- Register all Web Flow definitions under /WEB-INF/flows/**/*-flow.xml -->
<webflow:flow-registry id="flowRegistry"
base-path="/WEB-INF/flows" flow-builder-services="flowBuilderServices">
<webflow:flow-location-pattern value="/**/*-flow.xml" />
</webflow:flow-registry>
<!-- Deploy a flow executor -->
<webflow:flow-executor id="flowExecutor" />
<!-- Configure flow builder services -->
<!-- Configure view service -->
<webflow:flow-builder-services id="flowBuilderServices"
view-factory-creator="mvcViewFactoryCreator" />
<!-- Web Flow components -->
<!-- Install flow handler (FlowHandlerAdapter) -->
<!-- It dispatches URL requests to flows -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor" />
</bean>
<!-- Map Http request path to flows register in the registry -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="flowRegistry" />
<property name="order" value="0" />
</bean>
<bean id="mvcViewFactoryCreator"
class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="mvcViewResolver"/>
</bean>
Spring Webflow is built on spring web mvc, so the two can be used together.
I have learned that the problem with this combination is that when there is something misconfigured, the only symptom is "nothing happens". I ultimately ended up looking at the debug logs for org.springframework.web and org.springframework.webflow, then tracing into the spring source code to diagnose configuration issues.
The spring paradigm is aiming towards "convention over configuration". The problem I have had with it is that the conventions are not always well defined in a manner that someone already familiar with them can easily grasp.
The final "gotcha" that I had to resolve is that the convention for spring webflow is to put the flow xml files in the same folder as the jsp's.
In your example, you appear to be planning to switch between spring-webflow and unadorned web mvc behind the same view. Provided everything is correctly configured, for a given uri, whatever is in the webflow registry will trump whatever is in the UrlHandlerMapping (your annotations). This can create confusion if you're not aware of it.

Categories

Resources