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
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'm using dbunit with an h2 in-memory database to test the methods in a DAO class that I wrote. All tests in the suite used to pass successfully, but then I reorganized the directory structure of the project and now I'm getting a NoSuchTableException when I run the test suite. I feel that it's got to be some kind of build path error, but I've been banging my head over it for two days now and can't fix it.
Here's an excerpt from the test class containing some of the set-up methods:
#RunWith(PowerMockRunner.class)
#PrepareForTest(DAOUtilities.class)
public class FeedingScheduleDaoImplDBUnitTest extends DataSourceBasedDBTestCase {
private Connection connection;
private FeedingScheduleDaoImpl fsdi = new FeedingScheduleDaoImpl();
#Override
protected DataSource getDataSource() {
JdbcDataSource dataSource = new JdbcDataSource();
dataSource.setUrl("jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'");
dataSource.setUser("sa");
dataSource.setPassword("sa");
return dataSource;
}
#Override
protected IDataSet getDataSet() throws Exception {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("data.xml");
return new FlatXmlDataSetBuilder().build(inputStream);
}
#Override
protected DatabaseOperation getSetUpOperation() {
return DatabaseOperation.REFRESH;
}
#Override
protected DatabaseOperation getTearDownOperation() {
return DatabaseOperation.DELETE_ALL;
}
#Before
public void setUp() throws Exception {
super.setUp();
connection = getConnection().getConnection();
}
#After
public void tearDown() throws Exception {
super.tearDown();
}
#Test
public void givenDataSetEmptySchema_whenDataSetCreated_thenTablesAreEqual() throws Exception {
IDataSet expectedDataSet = getDataSet();
ITable expectedTable = expectedDataSet.getTable("animals");
IDataSet databaseDataSet = getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("animals");
Assertion.assertEquals(expectedTable, actualTable);
}
}
It's the return new FlatXmlDataSetBuilder().build(inputStream); that is actually generating the exception, but I suspect that's because the schema isn't being properly loaded in getDataSource() method.
Below is my new directory structure after the reorganization. The sql schema file and the xml data files needed for the tests are all in the src/test/resources directory.
eZoo directory structure
And here's the build section of my pom.xml. I haven't specified any source or resource directories for the build, and so if I'm understanding things correctly, that should land all of the resource files in the default target/test-classes directory. I've checked and they are in fact there.
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
</plugin>
</plugins>
</build>
Any tips or help would be much appreciated. I'm still learning how to use Maven, and I did this reorganization in an effort to better understand the standard Maven project structure, so I'm hoping to both fix what I broke and learn how to use Maven better.
After tinkering, I found a solution to my problem. I removed the following line from my xml files:
<!DOCTYPE xml>
Here's a link to another question and answer where I found the solution: https://stackoverflow.com/a/5915063.
I have a Spring Boot application that hosts a REST API.
Depending on which files get deployed, I want to be able to have it load additional controllers from what is essentially a "plugin" JAR file.
For example, I'd love to be able to do something like this:
java -jar myapp.jar -Dplugins.directory=/opt/myapp/plugins
Is this possible?
Note: these would not be loaded on the fly; once deployed, the set of plugins will remain fixed. I want one application jar that remains the same in every deployment, and the behavior of the application will be determined by the plugins that are deployed alongside it.
it may not 100% Satisfy your demand.
I have two suggestion.
the easy one.
java -jar stackoverflow-1.0-SNAPSHOT.jar --spring.profiles.active=prod
and put different value "#Profile" on your controller.
#RestController
#Profile("prod")
public class URLOneController {
#PostMapping(value = "/url", consumes="application/json", produces="application/json")
public ResponseEntity<HttpStatus> insertClaim(#RequestBody String messageBody) {
return new ResponseEntity<>(HttpStatus.OK);
}
}
second suggestion ,dynamic load beanDefiniton.
#Configuration
#ConditionalOnProperty(name="external.controller.enable",havingValue = "true")
public class ExternalClassDefinitionProcessor implements
BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
Class<?> aClass = null;
try {
aClass = contextClassLoader.loadClass("com.jin.learn.demo.UrlOneController");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
.genericBeanDefinition(aClass);
beanDefinitionBuilder.addPropertyReference("personDao", "personDao");
BeanDefinition personManagerBeanDefinition = beanDefinitionBuilder
.getRawBeanDefinition();
registry.registerBeanDefinition("UrlOneController",
personManagerBeanDefinition);
}
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory
beanFactory) throws BeansException {
}
}
package your controller into normal jar(not use spring-boot-maven-plugin )
run your app like this command line
java -Dloader.path="lib/,config/,/home/jin/Desktop/abc/target/abc-1.0-SNAPSHOT.jar" -jar stackoverflow-1.0-SNAPSHOT.jar --external.controller.enable=true
the extra contorller in abc-1.0-SNAPSHOT.jar and your main app is stackoverflow-1.0-SNAPSHOT.jar
tips:
stackoverflow-1.0-SNAPSHOT.jar should package zip format .
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layout>ZIP</layout>
</configuration>
</plugin>
I am new to AWS and I am currently trying to understand Lambda functions and to trigger it when I upload file to S3 bucket.
I wrote a handler class for this:
public class Hello implements RequestHandler<Employee, String> {
public String handleRequest(Employee input, Context context) {
context.getLogger().log("helloWorld");
return "Hello World " ;
}
}
This was just a basic and I could see the "helloworld" printed in logs in CloudWatch when I upload a file to S3 bucket.
But Now what I want to log the metadata of the file (fileName, createdTime etc.).
I went thru a sample template example in AWS Lambda page, where I can see using Nodejs, we have the event as the argument and we can extract the name and other fields using this field.
const aws = require('aws-sdk');
const s3 = new aws.S3({ apiVersion: '2006-03-01' });
exports.handler = (event, context, callback) => {
const bucket = event.Records[0].s3.bucket.name;
...
}
But as a Java developer, I tried to use S3EventNotification as the argument:
public class Hello implements RequestHandler<S3EventNotification, String> {
public String handleRequest(S3EventNotification input, Context context) {
context.getLogger().log(input.getRecords().get(0).getEventSource());
return "Hello World " ;
}
}
But I am getting below error:
An error occurred during JSON parsing: java.lang.RuntimeException
java.lang.RuntimeException: An error occurred during JSON parsing
Caused by: lambdainternal.util.ReflectUtil$ReflectException: java.lang.NoSuchMethodException: com.amazonaws.services.s3.event.S3EventNotification$S3ObjectEntity.<init>(java.lang.String, java.lang.Long, java.lang.String, java.lang.String)
Caused by: java.lang.NoSuchMethodException: com.amazonaws.services.s3.event.S3EventNotification$S3ObjectEntity.<init>(java.lang.String, java.lang.Long, java.lang.String, java.lang.String)
How can I achieve the same thing in Java? Thanks.
Try some variant of the following:
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.S3Event;
public class Hello implements RequestHandler<S3Event, Void> {
#Override
public Void handleRequest(S3Event s3event, Context context) {
try {
S3EventNotificationRecord record = s3event.getRecords().get(0);
String bkt = record.getS3().getBucket().getName();
String key = record.getS3().getObject().getKey().replace('+', ' ');
key = URLDecoder.decode(key, "UTF-8");
} catch (Exception e) {
// do something
}
return null;
}
}
And here are the corresponding dependencies that I used in pom.xml:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.11.228</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>2.0.1</version>
</dependency>
And here is the build specification from my pom.xml (which will cause dependent classes to be pulled into my built JAR):
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
None of this is very simple, unfortunately, but that's Java and Maven for you. AWS Lambda programming in Node.js or Python is much simpler (and more fun) than in Java, so if there's no strong requirement to write it in Java, you're better off not writing in Java.
Also note that if the Lambda is going to be invoked asynchronously then the output type should be Void rather than String (see docs).
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;