I get a JAXB marshalling error (cycle infinite loop) - posted at end of this question.
I know it's due to a 2 way object reference and I have used EclipseLink MOXy JAXB marshaller in a test case to resolve this specifying ID and IDREF and specified the JAXB provider using a jaxb.properties file containing
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
However the production code uses Spring OXM and I cannot see how to achieve a similar result using this.
I have added a jaxb.properties file but it isn't being used - I know this because I add an empty file as a test and it doesn't complain (like it did on the prototype test case).
How do I specify the JAXB marshaller to use?
It appears to be using:
org.eclipse.persistence.oxm.XMLMarshaller
whereas my working test case uses :
org.eclipse.persistence.jaxb.JAXBMarshaller
Exception:
javax.xml.bind.MarshalException
- with linked exception:
[Exception [EclipseLink-25037] (Eclipse Persistence Services -
2.6.1.v20150916-55dc7c3):
org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A cycle is detected in the object graph. This will
cause an infinite loop:
at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal
(JAXBMarshaller.java:487)
OK - to resolve this I specified (in the Spring OXM file)
<xml-inverse-reference mapped-by="myObject"
<xml-element xml-idref="true"
I only added the xml-idref="true" relationship
Related
In Jaxb 1.0 the xml validation is turned on by calling 'setValidating' on unmarshaller object:
JAXBContext jaxbContext = JAXBContext.newInstance(packageName);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setValidating(true);
In Jaxb 2.0 the validation is enhanced and setting up a schema is required:
Schema schema = schemaFactory.newSchema(file);
unmarshaller.setSchema(schema);
Looks like to use JAXB 2.0 validation the schema xsd file is a neccessary, requisite resource that must be provided in the application context.
While in JAXB 1.0 to turn on validation the schema file is not required (at least explicitly)
Question 1:
Does JAXB 1.0 really stores validation capabilities in its implementation (which comes from xjc) and xsd file is not required in the app/package/classpath runtime context?
Question 2:
In JAXB 2.0 is it possible to 'unsetSchema' for the unmarshaller - just give up validation (for performance purposes ... when I see that incoming xml payload is the same like the one I already validated earlier)?
Answer to question #2:
To turn off unmarshaller validation it is enough to reset schema to null:
unmarshaller.setSchema(null);
Question #1 remains open:
Does JAXB 2.0 need a schema file to be provided at runtime to perform validation during marshalling/unmarshalling ? ... or maybe we can force xjc complier with some options (like -nv) to generate implementation that has validation capabilities like JAXB 1.0 used to have. (just not to disclose xsd schema)
We are planning to upgrade our product to Web-logic 12.C and WebSphere 8 stack ( Earlier it was WLC 10.3.5 and WAS 7). But issue in one of the web service component causing entire application failed to deploy in web logic. It works perfectly fine with WebSphere 8.
When deploying the EAR, Application sever throws 'Exception [EclipseLink-59] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DescriptorException' . After more analysis, I found below code in one of the WebServce dependant class causing the problem,
#ExcludeAttribute
public Map getOperations(){
Map map = new HashMap();
//some operation
return map;
}
#ExcludeAttribute describes Runtime retention policies, which is defined as shown below
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface ExcludeAttribute {
}
getOperations method returns java.util.Map which does not work with RunTime retention annotations, but works with any other data types such as (Integer, Customer etc) . I have changed to java.uitl.HashMap and did not work.
I was able to fix this (rather I would call work around) by using following annotation,
#XmlTransient
I have no other clue why does it not working with java.uitl.Map. Any thoughts would really give thumbs up!! I have posted to Oracle support, even they have not came back yet. Is there any know issues with java.util.Map/Collection class with combination of WEblogic12c/Annotations.
[EDIT - 1]
To answer Doughan question, methods which return non collection data type does not throw any exception, for eg:
#ExcludeAttribute
public Integer getOperations(){
return 1;
}
Where #ExcludeAttribute is custom annotation defines '#Retention(RetentionPolicy.RUNTIME)', and I do not need to define #XmlTransient to ignore.
I am bit confused to with usage of retention run time annotation , and not sure if I need to keep it or should use XMLTransient annotation.
[Edit 2 ,Based on #Doughan's answer]
I understand that we need to explicitly annotate getter methods ( as #XMLTransient) if they are not to be mapped from Weblogic 12C, and this is no way related to RuntTime Retention annotations. So any stack upgrade to 12C should update code base with this annotation if there unmapped public getter methods. I think is pretty much answers my concerns.
Correct me if I am wrong.
The existing code base already has annotated with Runtime annotation, and I thought its the one causing issue.
Detailed stack trace follows
weblogic.application.ModuleException: [HTTP:101216]Servlet:
"com.chordiant.component.cxradecisions.decision.impl.internal.AssessmentDecisionInterfaceWebServiceWrapper"
failed to preload on startup in Web application: "/ra".
com.sun.xml.ws.spi.db.DatabindingException: Descriptor Exceptions:
Exception [EclipseLink-59] (Eclipse Persistence Services -
2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DescriptorException Exception
Description: The instance variable [responseButtons] is not defined in
the domain class [com.chordiant.dm.ra.bean.Assessment], or it is not
accessible. Internal Exception: java.lang.NoSuchFieldException:
responseButtons Mapping:
org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping[responseButtons]
Descriptor: XMLDescriptor(com.chordiant.dm.ra.bean.Assessment --> [])
Runtime Exceptions:
at com.sun.xml.ws.db.toplink.JAXBContextFactory.newContext(JAXBContextFactory.java:185)
at com.sun.xml.ws.spi.db.BindingContextFactory.create(BindingContextFactory.java:179)
at com.sun.xml.ws.model.AbstractSEIModelImpl$1.run(AbstractSEIModelImpl.java:211)
at com.sun.xml.ws.model.AbstractSEIModelImpl$1.run(AbstractSEIModelImpl.java:185)
And I have a method getResponseButtons() defined in Assessment class
#ExcludeAttribute
public Map getResponseButtons() {
Map map = new HashMap();
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
In WebLogic 12.1.1 you will need to annotate that property with #XmlTransient:
#ExcludeAttribute
public Map getOperations(){
Map map = new HashMap();
//some operation
return map;
}
#ExcludeAttribute is custom annotation created by us, which uses
#Retention(RetentionPolicy.RUNTIME), ( I have provided snippet of this
annotation)
Custom annotations do not affect how MOXy produces its mapping metadata. There is no way that it could, just because the annotation is called #ExcludeAttribute MOXy couldn't assume it should be treated like #XmlTransient.
But issue in one of the web service component causing entire
application failed to deploy in web logic. It works perfectly fine
with WebSphere 8.
EclipseLink MOXy is the default JAXB provider in WebLogic as of version 12.1.1. You may be hitting an issue where previously MOXy treated all properties with only a getmethod as write only properties. New versions of MOXy will ignore these properties unless they are explicitly annotated. This may have caused it to appear to you that the #ExcludeAttribute annotation was having an effect.
I am bit confused to with usage of retention run time annotation
This setting is related to whether or not you can access this annotation via reflection at runtime. Are you creating your own annotation for your own purposes?
When deploying the EAR, Application sever throws 'Exception
[EclipseLink-59] (Eclipse Persistence Services -
2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DescriptorException'
If the contents of that property are meant to be mapped could you share the complete stack trace?
I'm working on an update version of grail-oauth-plugin that support last spring-oauth
My plugin version works good and I have implemented a workin oauth2 server.
But now I want to add a custom-grant defined like this
def doWithSpring = {
myTokenGranter(MyTokenGranter)
xmlns oauth:"http://www.springframework.org/schema/security/oauth2"
oauth.'authorization-server'( /* ... many definitions here ... */){
/* ... many definitions here ... */
oauth.'custom-grant'('token-granter-ref': "myTokenGranter")
}
}
But I get an exception telling me:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myTokenGranter'
But the bean myTokenGranter is defined as you can see. And If I remove the custom-grant definition the project starts and I can access the myTokenGranter bean.
Looking to a fullstack trace I see that the exception occur in the spring oatuh2 server bean definition parse AuthorizationServerBeanDefinitionParser.java in the line where it try to find my bean
parserContext.getRegistry().getBeanDefinition(customGranterRef);
where customGranterRef = "myTokenGranter"
so I suspect there is a bug in Spring Ouath or in Grails BeanBuilder that does not let my "myTokenGranter" to be visible in the server parser. Or making some error in grails bean definition DSL.
Thank you for your interest.
Debugging the app more deeply I have found that the problem probably is in how grails BeanBuilder work in translating namespaced spring DSL.
If I debug the point where my bean is checked (in AuthorizationServerBeanDefinitionParser.java)
at row
parserContext.getRegistry().getBeanDefinition(customGranterRef);
if I check che result of
parserContext.getRegistry().getBeanDefinitionNames()
it show me only this beans
[org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.annotation.internalPersistenceAnnotationProcessor
org.springframework.aop.config.internalAutoProxyCreator
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0
org.springframework.transaction.interceptor.TransactionInterceptor#0
org.springframework.transaction.config.internalTransactionAdvisor
oauth2TokenGranter
oauth2AuthorizationCodeServices
oauth2AuthorizationRequestManager]
And not all other decleared beans...
The problem exist even if I move the ouath server declaration inside resources.xml, keeping my custom token granter bean declaration inside resources.groovy.
But the problem solves if I move the custom token bean declaration inside resources.xml.
I don't really know how the BeanBuilder DSL works, but it seems like the problem is there if there is a problem (your example works just fine in XML). Can you do it in two steps, so the bean definition for myTokenGranter is definitely available when the OAuth2 namepsace is handled?
Solved hacking Spring Security Oauth
see this commit
I perform refactoring and split controller into 2 controllers with:
#RequestMapping(value = "/graph.htm", method = RequestMethod.POST, params="first")
in first controller and:
#RequestMapping(value = "/graph.htm", method = RequestMethod.POST, params="second")
in second controller so these annotations lie in different files. When I build and use project all is fine (I put input HTML tag in my forms with different names: first and second).
But when I try to run JUnit controller test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:test-context.xml" })
I get trace:
Caused by: java.lang.IllegalStateException: Cannot map handler 'firstController'
to URL path [/graph.htm]: There is already handler
of type [class com.web.controller.SecondController] mapped.
at org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler(AbstractUrlHandlerMapping.java:294)
at org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler(AbstractUrlHandlerMapping.java:266)
at org.springframework.web.servlet.handler.AbstractDetectingUrlHandlerMapping.detectHandlers(AbstractDetectingUrlHandlerMapping.java:82)
at org.springframework.web.servlet.handler.AbstractDetectingUrlHandlerMapping.initApplicationContext(AbstractDetectingUrlHandlerMapping.java:58)
at org.springframework.context.support.ApplicationObjectSupport.initApplicationContext(ApplicationObjectSupport.java:119)
at org.springframework.web.context.support.WebApplicationObjectSupport.initApplicationContext(WebApplicationObjectSupport.java:72)
at org.springframework.context.support.ApplicationObjectSupport.setApplicationContext(ApplicationObjectSupport.java:73)
at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:117)
at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:92)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:399)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1479)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524)
When I comment out this:
#RequestMapping(value = "/graph.htm", method = RequestMethod.POST, params="second")
in second controller individual test for first controller successfully completed.
To resolve this issue I may use different URLs (value in #RequestMapping) but I don't understand why request mapping resolved for params in my production build of application and fail with SpringJUnit4ClassRunner.
Any help welcome!
PS. I use Spring 3.2.
PPS. I found mostly same issue Can I have the same mapping value with different param in a different Spring controller? but according to answers my production build also must fail?! But I run production build successfully!!
Also refer to:
#RequestMapping with 2 params in render method
Spring MVC 3: same #RequestMapping in different controllers, with centralised XML URL mapping (hybrid xml/annotations approach)
*PPS.
I check official docs for 3.2:
http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html#params%28%29
In a Servlet environment, parameter mappings are considered as restrictions
that are enforced at the type level. The primary path mapping (i.e. the
specified URI value) still has to uniquely identify the target handler, with
parameter mappings simply expressing preconditions for invoking the handler.
So seems I perform illegal coding practice...
This is what I understand when reading the official doc quoted in your question :
In a Servlet environment, parameter mappings are considered as restrictions
that are enforced at the type level. The primary path mapping (i.e. the
specified URI value) still has to uniquely identify the target handler within the class, with
parameter mappings simply expressing preconditions for invoking the handler.
I added the words "within the class".
And please note the enforced at type level. As I understand, it means that : in a servlet env. declaring the params at method level is quite the same as declaring the params at type level (at least if you only have only one method in your class).
Finally, if you take care to this sentence (same source):
When used at the type level, all method-level mappings inherit this parameter restriction (i.e. the type-level restriction gets checked before the handler method is even resolved).
I think all of this summarize why your are not doing illegal coding.
Regarding unit tests:
What is also important here are the words "In a Servlet environment. Obviously, when running unit tests : your not in a Servlet environment and that's probably why it is failing.
My neighbour colleague help me with debugging issue.
We compare production and test environment and found difference in context XML configuration.
Previous test configuration which fail:
<bean name="handlerMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<bean name="handlerAdapter"
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
New and working test context configuration:
<bean name="handlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean name="handlerAdapter"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
Different spring classes use different mapping schema. Old uses per classes, newer uses per methods!!
We are using cxf version 2.5.2 and we expose and consume couple of restful web services using cxf jaxrs.
Any idea how to throw exceptions from server to client ?
I tried defining a custom exception mapper by implementing ExceptionMapper interface (toResponse method) and added the bean in cxf jaxrs:server providers list.
Client side : Implemented ResponseExceptionMapper (fromResonse method) and added the bean in cxf jaxrs:client providers list. But this doesnt seem to work.
Exception is a custom exception that extends java.lang.Exception.
Got "IllegalAnnotationsException 2 counts of IllegalAnnotationExceptions StackTraceElement does not have a no-arg default constructor"
Found http://java.net/jira/browse/JAXB-814 and upgrading to jaxb-impl 2.2.5 resolved that issue.
But at the end, i am struck with the following exception in server side (during client invocation) :
org.apache.cxf.jaxrs.provider.AbstractJAXBProvider :
com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions blueprints.common.util.BlueprintsException does not have a no-arg default constructor"
and in client side :
JAXBException occurred : 1 counts of IllegalAnnotationExceptions.
java.lang.ClassCastException: org.apache.cxf.helpers.LoadingByteArrayOutputStream$1 cannot be cast to myExceptionClass:java.lang.ClassCastException" when i typecast Response.getEntity()) tp myExceptionClass in fromResponse (jaxrs provider that implements ResponseExceptionMapper)
Has anybody else faced similar issues?
Do we need to add custom out interceptors ? The cxf doc doesnt provide example for exception handling using spring config.
Edit based on jigar's comment:
After adding default constructor, the entity in response contains
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<blueprintsServiceException>
<stackTrace/>
<stackTrace/>
<stackTrace/>
<stackTrace/>
...
</blueprintsServiceException>`
and i still get java.lang.ClassCastException:
org.apache.cxf.helpers.LoadingByteArrayOutputStream$1 cannot be cast to blueprints.server.exception.BlueprintsServiceException' when i typecast Response.getEntity()) to myExceptionClass in fromResponse
(jaxrs provider that implements ResponseExceptionMapper)
Thanks,
Gayathri
in BlueprintsException you need to provide a default constructor,
You might have overloaded the constructor which hides the default constructor, So you need to provide default constructor explicitly