EDITS AT THE BOTTOM
Currently experiencing one error after another. It seems I make a step forward and have to take 2 steps back :) Unfortunately I have nobody locally that I can pair with so a lot of my debugging is being done over Google and SO.
I'm not very familiar with jaxb and using it to make soap calls (which is what I'm currently trying to do - connect to soap service) but I was told that this is the easiest approach for what I'm wanting to do and that I should look into this since I'm using spring-boot in the rest of the project so I found a tutorial (here) and started there.
Here is the plugin section of my pom that creates the package of classes based on the wsdl:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.12.3</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<generatePackage>vantiveGenericWebService.wsdl</generatePackage>
<schemas>
<schema>
<url>http://hostname:port/GenericWebService/ws?service=InstalledComponentService2&appl=vantive&wsdl</url>
</schema>
</schemas>
</configuration>
</plugin>
I'm able to create the wsdl classes fine.
I created a client class:
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import vantiveGenericWebService.wsdl.GetICDetailsByAssetTag;
import vantiveGenericWebService.wsdl.GetICDetailsByAssetTagResponse;
#Component
public class VantiveGenericWebServiceClient extends WebServiceGatewaySupport {
Logger log = Logger.getLogger(VantiveGenericWebServiceClient.class.getName());
public GetICDetailsByAssetTagResponse getICDetailsByAssetTag(String assetTag) {
GetICDetailsByAssetTag request = new GetICDetailsByAssetTag();
request.setAssetTag(assetTag);
log.info("Requesting asset tag for: " + assetTag);
GetICDetailsByAssetTagResponse response = (GetICDetailsByAssetTagResponse) getWebServiceTemplate().marshalSendAndReceive("http://hostname:port/GenericWebService/ws?service=InstalledComponentService2&appl=vantive", request);
return response;
}
}
as well as a client config class:
#Configuration
public class VantiveGenericWebServiceConfig {
#Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("vantiveGenericWebService.wsdl");
return marshaller;
}
#Bean
public VantiveGenericWebServiceClient vantiveGenericWebServiceClient(Jaxb2Marshaller marshaller) {
VantiveGenericWebServiceClient client = new VantiveGenericWebServiceClient();
client.setDefaultUri("http://hostname:port/GenericWebService/ws?&service=InstalledComponentService2&appl=vantive");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
// ClientInterceptor[] interceptors = new ClientInterceptor[] { new ClientInterceptor() {
// #Override
// public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
// return false;
// }
//
// #Override
// public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException {
// return true;
// }
//
// #Override
// public boolean handleFault(MessageContext messageContext) throws WebServiceClientException {
// return true;
// }
//
// #Override
// public void afterCompletion(MessageContext messageContext, Exception e) throws WebServiceClientException {
//
// }
// }};
// client.setInterceptors(interceptors);
return client;
}
}
Now on to the error! First I was getting one that looked like this:
org.springframework.oxm.MarshallingFailureException: JAXB marshalling exception; nested exception is javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.internal.SAXException2: unable to marshal type "vantiveGenericWebService.wsdl.GetICDetailsByAssetTag" as an element because it is missing an #XmlRootElement annotation]
so then I modified the GetICDetailsByAssetTag class (a class that was generated from the wsdl) to look like this:
#XmlRootElement(name = "assetTag")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "getICDetailsByAssetTag", propOrder = {
"assetTag"
})
public class GetICDetailsByAssetTag {
which I'm not 100% sure is the correct xml root but the error goes away. Now my 2nd (and current) error is this:
org.springframework.oxm.UnmarshallingFailureException: JAXB unmarshalling exception; nested exception is javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Fault"). Expected elements are <{http://hostname/vantive/ws/InstalledComponentService2}DuplicateException>,<{http://hostname/vantive/ws/InstalledComponentService2}FunctionalException>,<{http://hostname/vantive/ws/InstalledComponentService2}GetICDetailsByAssetTagResponse>,<{http://hostname/vantive/ws/InstalledComponentService2}GetInstalledComponentDetailsByAssetTagAndStatusResponse>,<{http://hostname/vantive/ws/InstalledComponentService2}InvalidValuesException>,<{http://hostname/vantive/ws/InstalledComponentService2}SetClientDeviceXrefResponse>,<{http://hostname/vantive/ws/InstalledComponentService2}SetInstalledComponentAssetTagResponse>,<{http://hostname/vantive/ws/InstalledComponentService2}TechnicalException>,<{http://hostname/vantive/ws/InstalledComponentService2}assetTag>,<{http://hostname/vantive/ws/InstalledComponentService2}getICDetailsByAssetTag>,<{http://hostname/vantive/ws/InstalledComponentService2}getInstalledComponentDetailsByAssetTagAndStatus>,<{http://hostname/vantive/ws/InstalledComponentService2}installedComponentAssetTagDetails>,<{http://hostname/vantive/ws/InstalledComponentService2}installedComponentDetails>,<{http://hostname/vantive/ws/InstalledComponentService2}setClientDeviceXref>,<{http://com.savvis.it/vantive/ws/InstalledComponentService2}setClientDeviceXrefResult>,<{http://hostname/vantive/ws/InstalledComponentService2}setInstalledComponentAssetTag>,<{http://hostname/vantive/ws/InstalledComponentService2}setInstalledComponentAssetTagResult>
I can post the full stacktraces if necessary. I'm omitting right now for space.
Believe me when I say I have scoured Google and SO looking at all the posts and suggested answers for these errors (that's why I have the currently commented out interceptor code in my config) and I just can't seem to find anything that 1. fixes it and 2. explains what exactly I'm doing wrong. I don't very much care for having something that works but I also where can't tell you what's happening.
Coincidentally, the interceptor portion makes it so no error is thrown but then my response is null.
I have a feeling that my problem is going to be a simple one but since this is my first time doing something like this it's just not jumping out at me. Right now I'm just wanting to send my request and get the valid response that I'm expecting and I'll be happy.
For S&Gs, here's my soap request body too (taken from SoapUI):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ins="http://hostname/vantive/ws/InstalledComponentService2">
<soapenv:Header/>
<soapenv:Body>
<ins:getICDetailsByAssetTag>
<assetTag>asserTag</assetTag>
</ins:getICDetailsByAssetTag>
</soapenv:Body>
</soapenv:Envelope>
EDIT
After looking at this I can confirm that my ObjectFactory class (that was created via the wsdl) does have create methods that are wrapped with the JAXBElement wrapper, have #XmlElementDecl(namespace = "http://hostname/vantive/ws/InstalledComponentService2", xxx), and also name tags that correspond to the class that is wrapped by the JAXBElement wrapper.
EDIT 2
Just for clarity's sake, here is my package-info class
#XmlSchema(namespace = "http://hostname/vantive/ws/InstalledComponentService2")
package vantiveGenericWebService.wsdl;
Related
We have some APIs we use in our application that are not accessible from local developer machines due to firewalls.
I want to use mockServer to mock some of these API so we can develop locally.
When running tests mockServer can be started and stopped using the maven build phases process-test-classes and verify respectively.
How can I get it to run when I start the application with mvn spring-boot:run ?
It's possible to override beans on springboot.
So you can use your beans and switch for mock values as you need
The example bellow is overriding services and using mock as you prefer but you can use interfaces as well.
Creating a service
#Service
public class ServiceReal {
#Autowired(required = false) // must be required=false. May be disabled by using mock configuration
private JdbcTemplate jdbcTemplate;
public String getInfo() {
return jdbcTemplate...// get a real value from database
}
}
Creating a mock service
#Service
#Primary
#Profile("mocklocal")
public class ServiceMock extend ServiceReal {
#Override
public String getInfo() {
return "Mocked value"
}
}
Config beans to choose one of them on properties later
#Profile("mocklocal")
#PropertySource("classpath:application-mocklocal.properties")
#Configuration
public class ConfigMock {
private static final String PROP_VALUE_TRUE = "true";
private static final boolean PROP_FALSE_DEFAULT_MISSING = false;
private static final String PROP_SERVICE_REAL = "mocklocal.service.real";
private static final String PROP_SERVICE2_REAL = "mocklocal.service2.real";
#Bean
#ConditionalOnProperty( value = PROP_SERVICE_REAL, havingValue = PROP_VALUE_TRUE, matchIfMissing = PROP_FALSE_DEFAULT_MISSING)
public ServiceReal serviceReal(){
return new ServiceMock();
}
#Bean
#ConditionalOnProperty( value = PROP_SERVICE2_REAL, havingValue = PROP_VALUE_TRUE, matchIfMissing = PROP_FALSE_DEFAULT_MISSING)
public Service2Real service2Real(){
return new Service2Mock();
}
}
Config your application-mocklocal.properties to use mock
# using ConfigMock
spring.profiles.active=mocklocal
# settig spring to override service and use mock
spring.main.allow-bean-definition-overriding=true
# disable some configuration not required in mocks. you can adjust for amqp, database or other configuration
spring.autoconfigure.exclude[0]=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
spring.autoconfigure.exclude[1]=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
spring.autoconfigure.exclude[2]=org.springframework.boot.autoconfigure.orm.jpa.DataSourceTransactionManagerAutoConfiguration
# enable your service to use mocks not real services
mocklocal.service.real=true
mocklocal.service2.real=true
so if you start your app using --spring.profiles.active=mocklocal you will got mock values
And you can use on tests as well
#ExtendWith(SpringExtension.class)
#AutoConfigureMockMvc
#SpringBootTest
#TestPropertySource(locations = "classpath:application-mocklocal.properties")
public class RunIntegrationTests {
#Autowired
private MockMvc mockMvc;
#Test
public void run() throws Exception{
...
}
}
When running tests mockServer can be started and stopped using the maven build phases process-test-classes and verify respectively.
So there must be some (pom) configuration like:
<plugin>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-maven-plugin</artifactId>
<version>3.10.8</version>
<configuration>
<serverPort>1080</serverPort>
<proxyPort>1090</proxyPort>
<logLevel>DEBUG</logLevel>
<initializationClass>org.mockserver.maven.ExampleInitializationClass</initializationClass>
</configuration>
<executions>
<execution>
<id>process-test-classes</id>
<phase>process-test-classes</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<phase>verify</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
This would start a mock server at process-test-classes (so before test phase) and stop it at validate (so after (post-)integration-test phase).
(link1, link2)
How can I get it to run when I start the application with mvn spring-boot:run ?
To run it with mvn spring-boot:run:
Just run mvn mockserver:start spring-boot:run! (pack it into a script/IDE launch..) (recommended)
Implement custom plugin, which commbines spring-boot-maven and mockserver-maven-plugin... (and then run mvn com.example:custom-plugin:run)
.
I had created a MockServer for my team once, for quite a similar purpose here (fortunately a short demo is also available). You can set up this server independently (say on a localhost) and add the request (url and payloads) with the corresponding response json you want to this server.
The one time change you need to do inside your project will be to route all your API request to this Mockserver during development/testing, which can be done by changing the base url of all the APIs you will be using and setting up the mockserver with appropriate json request and response. It can be done as simple as this:
public class BaseUrlLoader {
public static String NEWSRIVER_BASE_URL;
public static String FACEBOOK_BASE_URL;
public static String TWITTER_BASE_URL;
private static final String MOCKSERVER_BASE_URL = "mocksrvr.herokuapp.com/TEAM-SECRET-KEY";
public static void load(){
Properties properties= new Properties();
String activeProfile;
try{
properties.load(ClassLoader.getSystemResourceAsStream("application.properties"));
} catch (IOException e) {
System.out.println("Not able to load the application.properties file");
return;
}
activeProfile = properties.getProperty("spring.profiles.active");
System.out.println("Using "+activeProfile);
if(activeProfile.equals("Test")){
NEWSRIVER_BASE_URL=MOCKSERVER_BASE_URL;
FACEBOOK_BASE_URL= MOCKSERVER_BASE_URL;
TWITTER_BASE_URL= MOCKSERVER_BASE_URL;
}else{
NEWSRIVER_BASE_URL="api.newsriver.io";
FACEBOOK_BASE_URL="api.facebook.com";
TWITTER_BASE_URL="api.twitter.com";
}
System.out.println(NEWSRIVER_BASE_URL);
}
}
// Example- Use APIs as
public class NewsFetch {
...
public NewsFetch(){ BaseUrlLoader.load(); }
private URI buildURL(APIQuery apiQuery) throws URISyntaxException {
String mainURL = BaseUrlLoader.NEWSRIVER_BASE_URL+"v2/search";
URIBuilder url = new URIBuilder(mainURL);
url.addParameter("query", apiQuery.getLuceneQuery());
url.addParameter("soryBy", apiQuery.getSortBy());
url.addParameter("sortOrder", apiQuery.getSortOrder());
url.addParameter("limit", apiQuery.getLimit());
return url.build();
}
public HttpResponse <String> fetch(APIQuery apiQuery) throws URISyntaxException, IOException, InterruptedException {
URI uri = buildURL(apiQuery);
HttpRequest request = HttpRequest.newBuilder()
.GET()
.header("Authorization", KEY)
.uri(uri)
.build();
...
}
}
// and add the request like http://mocksrvr.herokuapp.com/TEAM-SECRET-KEY/v2/search/... to the Mockserver with the response you want.
The baseurl will change according to the current active profile. This mockserver is simple and can even be integrated with the Slackbot. See more in the readme file. There can be many bugs in the project and contributions will be appreciated.
I have a large Spring application that is set up without XML using only annotations. I have made some changes to this application and have a separate project with what should be almost all the same code. However, in this separate project, Togglz seems to be using some sort of default config instead of the TogglzConfig file I've set up.
The first sign that something was wrong was when I couldn't access the Togglz console. I get a 403 Forbidden error despite my config being set to allow anyone to use it (as shown on the Togglz site). I then did some tests and tried to see a list of features and the list is empty when I call FeatureContext.getFeatureManager().getFeatures() despite my Feature class having several features included. This is why I think it's using some sort of default.
TogglzConfiguration.java
public enum Features implements Feature {
FEATURE1,
FEATURE2,
FEATURE3,
FEATURE4,
FEATURE5;
public boolean isActive() {
return FeatureContext.getFeatureManager().isActive(this);
}
}
TogglzConfiguration.java
#Component
public class TogglzConfiguration implements TogglzConfig {
public Class<? extends Feature> getFeatureClass() {
return Features.class;
}
public StateRepository getStateRepository() {
File properties = [internal call to property file];
try {
return new FileBasedStateRepository(properties);
} catch (Exception e) {
throw new TogglzConfigException("Error getting Togglz configuration from " + properties + ".", e);
}
}
#Override
public UserProvider getUserProvider() {
return new UserProvider() {
#Override
public FeatureUser getCurrentUser() {
return new SimpleFeatureUser("admin", true);
}
};
}
}
SpringConfiguration.java
#EnableTransactionManagement
#Configuration
#ComponentScan(basePackages = { "root package for the entire project" }, excludeFilters =
#ComponentScan.Filter(type=FilterType.ANNOTATION, value=Controller.class))
public class SpringConfiguration {
#Bean
public TransformerFactory transformerFactory() {
return TransformerFactory.newInstance();
}
#Bean
public DocumentBuilderFactory documentBuilderfactory() {
return DocumentBuilderFactory.newInstance();
}
#Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
My project finds a bunch of other beans set up with the #Component annotation. I don't know if the problem is that this component isn't being picked up at all or if Togglz simply isn't using it for some reason. I tried printing the name of the FeatureManager returned by FeatureContext.getFeaturemanager() and it is FallbackTestFeatureManager so this seems to confirm my suspicion that it's just not using my config at all.
Anyone have any ideas on what I can check? I'm flat out of ideas, especially since this is working with an almost completely the same IntelliJ project on my machine right now. I just can't find out what's different about the Togglz setup or the Spring configurations. Thanks in advance for your help.
I finally had my light bulb moment and solved this problem. In case anyone else has a similar issue, it seems my mistake was having the Togglz testing and JUnit dependencies added to my project but not limiting them to the test scope. I overlooked that part of the site.
<!-- Togglz testing support -->
<dependency>
<groupId>org.togglz</groupId>
<artifactId>togglz-testing</artifactId>
<version>2.5.0.Final</version>
<scope>test</scope>
</dependency>
Without that scope, I assume these were overriding the Togglz configuration I created with a default test configuration and that was causing my issue.
I am trying to serve a static file in camel routes.
The routes in my main class contains this piece of code:
public final void configure() throws Exception {
// declaring camel routes
// match on uri prefix must be true when parameters are passed as part of the uri
// for example, "http://localhost/hello/rick"
// http.port is in local.properties file user-api
from("jetty:http://0.0.0.0:{{http.port}}/user/dist/?matchOnUriPrefix=true")
.process( new StaticProcessor( "help", "index.html", "dist"))
.routeId( "static");
from("jetty:http://0.0.0.0:{{http.port}}/user?matchOnUriPrefix=true")
.to("cxfbean:userService");
}
This works good. When I hit the url: http://xxxx:8086/user/dist/index.html, my index page is rendered and the url shows to behttp://xxxx:8086/user/dist/ in url bar.
But when I reload the page (press F5), the url becomes: http://xxxx:8086/user/dist// and I get error like:
This page should have been replaced by Swagger. Do you have the
following in your application's pom.xml as the only reference to the
swagger-maven-plugin?
<build>
<plugins>
<plugin>
<groupId>com.github.kongchen</groupId>
<artifactId>swagger-maven-plugin</artifactId>
<executions>
<execution>
<id>swagger</id>
<phase>compile</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
I have this dependency in my effective POM. So what am I missing?
I wish to achieve that any url with http://clv035sl-8947d6:8888/user/dist should route the call to index.html. Why I need to explictly write index.html at end of the url?
Any help/ suggestion will be appreciated.
I made a simple JUnit Test case to test your scenario based on this blog post.
Where are the implementation of the StaticProcessor class? I've implemented something for this scenario that is quite similar (IMHO):
public void configure() throws Exception {
from("jetty:http://0.0.0.0:8080/user/dist?matchOnUriPrefix=true").process(new Processor() {
public void process(Exchange exchange) throws Exception {
Message in = exchange.getIn();
String relativepath = in.getHeader(Exchange.HTTP_PATH, String.class);
String requestPath = in.getHeader("CamelServletContextPath", String.class); //CamelServletContextPath
if (relativepath.isEmpty() || relativepath.equals("/")) {
relativepath = "index.html";
}
final String formattedPath = String.format("%s/%s", requestPath, relativepath);
InputStream pathStream = this.getClass().getResourceAsStream(formattedPath);
Path path = FileSystems.getDefault().getPath(this.getClass().getResource(formattedPath).getPath());
Message out = exchange.getOut();
try {
out.setBody(IOUtils.toByteArray(pathStream));
out.setHeader(Exchange.CONTENT_TYPE, Files.probeContentType(path));
} catch (IOException e) {
out.setBody(relativepath + " not found.");
out.setHeader(Exchange.HTTP_RESPONSE_CODE, "404");
}
}
}).routeId("static");
}
It takes from the classpath the resources that needed to be exposed and set the out message to the response. Please, take a look at the entire test case.
I've tested the following URLs:
http://localhost:8080/user/dist/
http://localhost:8080/user/dist
http://localhost:8080/user/dist/index.html
Please note that I added the swagger plugin dependency just like you did.
Let me know if that helps or point where the StaticProcessor implementation is that I may test with it and edit my answer.
Cheers
I was working on mule 3.5.1, when I upgrade to mule 3.6 version, getting compile time error for following class:
import org.mule.module.jersey.MuleResponseWriter;
import com.sun.jersey.spi.container.ContainerResponse;
public class GLExportTransformer extends AbstractMessageTransformer {
public List<GLExport> methodType(#Payload MuleResponseWriter content){
List<GLExport> glExportList = (List<GLExport>) content;
System.out.println("Java payload is -->"+glExportList.getClass());
return glExportList ;
}
#Override
public Object transformMessage(MuleMessage message, String outputEncoding)throws TransformerException {
ContainerResponse cr = (ContainerResponse) message.getInvocationProperty("jersey_response");
List<GLExport> res = (List<GLExport>)cr.getResponse().getEntity();
System.out.println("Response from QB is -->"+res);
return res;
}
}
<custom-transformer name="StringToNameString" class="com.trinet.qb.utils.GLExportTransformer" doc:name="GL Export Transformer"/>
Compile time error:
The type org.mule.module.jersey.MuleResponseWriter is not visible
The import com.sun.jersey cannot be resolved
How do I resolve this?
In my Anypoint Studio shows Mule3.6 uses all jersey related jar uses 2.11 version of jar files. Using Java 1.7 version.
EDIT:
Here is my rest component(GLExportService):
#POST
#Path("/post")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public List<GLExport> postOperation(#Payload String content) throws ParseException {
System.out.println("Content from Reporting page-->\n\n"+content+"\n\n");
JSONParser jsonParser = new JSONParser();
Object jsonObjectInstance =null;
try {
jsonObjectInstance = jsonParser.parse(new StringReader(content));
} catch (ParseException e) {
System.out.println(e.getLocalizedMessage());
}
// parse json and assign to dto as glExportList
return glExportList;
Here is my mule flows:
<http:inbound-endpoint exchange-pattern="request-response" host="${hostname}" port="${glport}" path="QBJournalExport/QBGLRest" doc:name="HTTP"/>
<jersey:resources doc:name="REST">
<component class="com.qb.rest.GLExportService"/>
</jersey:resources>
<set-session-variable variableName="accessToken" value="#[payload.get(0).get('ACCESS_TOKEN')]" doc:name="Access token"/>
<set-session-variable variableName="accessTokenSecret" value="#[payload.get(0).get('ACCESS_TOKEN_SECRET')]" doc:name="Access Secret"/>
<set-session-variable variableName="realmId" value="#[payload.get(0).get('ACCT_SYSTEM_COMPANY_ID')]" doc:name="Company ID"/>
<set-session-variable variableName="quickbooksClient" value="#[com.qb.utils.QuickbooksUtils.getQuickbooksClient(sessionVars['accessToken'],sessionVars['accessTokenSecret'],'${consumerKey}','${consumerSecret}','${appToken}',sessionVars['realmId'])]" doc:name="QB Client"/>
<custom-transformer name="StringToNameString" class="com.qb.utils.GLExportTransformer" doc:name="GL Export Transformer"/>
<set-payload value="#[com.qb.utils.CreateJournalEntry.createJournalEntry(payload,sessionVars['accessToken'],sessionVars['accessTokenSecret'],'${consumerKey}','${consumerSecret}','${appToken}', sessionVars['realmId'])]" doc:name="Create Journal Entry"/>
import org.glassfish.jersey.server.ContainerResponse;
public class GLExportTransformer extends AbstractMessageTransformer {
#Override
public Object transformMessage(MuleMessage message, String outputEncoding)throws TransformerException {
ContainerResponse cr = (ContainerResponse) message.getInvocationProperty("jersey_response");
List<GLExport> res = (List<GLExport>)cr.getEntity();
return res;
}
}
method called methodType was a dummy code.
Try making the parameter type java.util.Object, and removing the import. You are immediately casting it to List<GLExport> anyway, so you don't appear to need that type.
We indeed made MuleResponseWriter package only, but that's not the root of your problem. In Mule 3.6 we upgraded from Jersey 1.6 to 2.11. Jersey 2 is quite different, it even includes a package rename from com.sun.jersey to org.glassfish.jersey. You can find more information about the upgrade in this post, including a link to Jersey's migration guide: http://blogs.mulesoft.org/mule-3-6-api/
What I don't understand anyway, is why you need to access the ContainerResponse in your transformer instead of having your jersey resource set the message payload to the List directly.
Regards
It seems they made the class org.mule.module.jersey.MuleResponseWriter package only.
This could be because the class was never part of the public Mule API or just minor typo.
Anyways, as it is right now there is no much you can do.
The only hack is to place the transformer and any class that references org.mule.module.jersey.MuleResponseWriter inside a package named:
org.mule.module.jersey
BUT THIS IS A HACK, and I wouldn't advise it.
I'll try to find out if was made on purpose and let you know ;)
We are trying to track down a bug. We get the above error in the logs.
Can anyone explain what this message means? Are there any typical reasons for getting this message?
The stacktrace is:
org.apache.axiom.om.OMException: java.lang.IllegalArgumentException: local part cannot be "null" when creating a QName
at org.apache.axiom.om.impl.builder.StAXOMBuilder.next(StAXOMBuilder.java:206)
at org.apache.axiom.om.impl.llom.OMNodeImpl.build(OMNodeImpl.java:318)
at org.apache.axiom.om.impl.llom.OMElementImpl.build(OMElementImpl.java:618)
at org.apache.axis2.jaxws.message.util.impl.SAAJConverterImpl.toOM(SAAJConverterImpl.java:147)
at org.apache.axis2.jaxws.message.impl.XMLPartImpl._convertSE2OM(XMLPartImpl.java:77)
at org.apache.axis2.jaxws.message.impl.XMLPartBase.getContentAsOMElement(XMLPartBase.java:203)
at org.apache.axis2.jaxws.message.impl.XMLPartBase.getAsOMElement(XMLPartBase.java:255)
at org.apache.axis2.jaxws.message.impl.MessageImpl.getAsOMElement(MessageImpl.java:464)
at org.apache.axis2.jaxws.message.util.MessageUtils.putMessageOnMessageContext(MessageUtils.java:202)
at org.apache.axis2.jaxws.core.controller.AxisInvocationController.prepareRequest(AxisInvocationController.java:370)
at org.apache.axis2.jaxws.core.controller.InvocationController.invoke(InvocationController.java:120)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invokeSEIMethod(JAXWSProxyHandler.java:317)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invoke(JAXWSProxyHandler.java:148)
I got the same error message (local part cannot be "null" when creating a QName) while trying to construct a org.w3c.dom.Document from String. The problem went away after calling setNamespaceAware(true) on DocumentBuilderFactory. Working code snippet is given below.
private static Document getDocumentFromString(final String xmlContent)
throws Exception
{
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
try
{
return documentBuilderFactory
.newDocumentBuilder()
.parse(new InputSource(new StringReader(xmlContent)));
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
It means you are creating a DOM element or attribute using one of the namespace methods like createElementNS thus
document.createElementNS(namespace, null)
or createElementNS or setAttrbuteNS
and the second argument, the qname is null, or includes a prefix but no local part as in "foo:".
EDIT:
I would try to run the XML it's parsing through a validator. It's likely there's some tag or attribute name like foo: or foo:bar:baz that is a valid XML identifier but invalid according to the additional restrictions introduced by XML namespaces.
After whole hours in searching, I just wanted to share the Answer in this thread helped me with a Talend code migration - involving SOAP messages - from java8 to java11.
// Used libraries
import java.io.ByteArrayInputStream;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.soap.SOAPBody;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
...
// This is the node I want to replace: "<DataArea><Contact/></DataArea>"
// <SOAP-ENV:Body> > SOAP Action (e.g. <ns:GetContact>) > <GetContactRequest> > <DataArea>
SOAPBody soapBodyRequest = objSOAPMessage.getSOAPPart().getEnvelope().getBody();
Node nodeDataArea = soapBodyRequest.getFirstChild().getFirstChild().getFirstChild();
// Build a valid Node object starting from a string e.g. "<Contact> etc etc nested-etc </Contact>"
DocumentBuilderFactory objDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
// As per java11, this is essential. It forces the Factory to consider the ':' as a namespace separator rather than part of a tag.
objDocumentBuilderFactory.setNamespaceAware(true);
// Create the node to replace "<DataArea><Contact/></DataArea>" with "<DataArea><Contact>content and nested tags</Contact></DataArea>"
Node nodeParsedFromString = objDocumentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(strDataArea.getBytes())).getDocumentElement();
// Import the newly parsed Node object in the request envelop being built and replace the existing node.
nodeDataArea.replaceChild(
/*newChild*/nodeDataArea.getOwnerDocument().importNode(nodeParsedFromString, true),
/*oldChild*/nodeDataArea.getFirstChild()
);
This throws the Local part cannot be "null" when creating a QName exception if you don't put the .setNamespaceAware(true) instruction
Although this is an old thread, I hope this answer would help some one else searching this error.
I have faced the same error when I was trying to build a web app using maven-enunciate-cxf-plugin:1.28.
For me this was caused after I added a checked exception to my web service signature:
#WebMethod(operationName = "enquirySth")
public IBANResponse enquirySth(String input) throws I
InvalidInputException { ...
I have used JAX-WS Spec for exception throwing but no success. At the end I have found this issue in Enunciate issue tracker system which indicates this issue is resolved in current version, but I think it still exist.
Finally I have done following workaround to fix my problem:
adding #XmlRootElement to my FaultBean.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "FaultBean",propOrder = {"errorDescription", "errorCode"})
public class FaultBean implements Serializable {
#XmlElement(required = true, nillable = true)
protected String errorDescription;
#XmlElement(required = true, nillable = true)
protected String errorCode;
public FaultBean() {
}
public String getErrorDescription() {
return this.errorDescription;
}
public void setErrorDescription(String var1) {
this.errorDescription = var1;
}
public String getErrorCode() {
return this.errorCode;
}
public void setErrorCode(String var1) {
this.errorCode = var1;
}
}
That's it. Hope it helps.