SOAP path resolution for dependent XSD-file not understood - soap

I have two XSD-files, one is imported to the other. When retrieving the WSDL (via SoapUI) the imported xsd-file is not found.
Error loading [http://localhost:8294/authentication/shared-environment.xsd]:
org.apache.xmlbeans.XmlException: org.apache.xmlbeans.XmlException: error:
Unexpected end of file after null
The two of the xsd-files reside in the same folder:
src/main/resources
- auth-attributes.xsd
- shared-environment.xsd
The "auth-attributes.xsd" looks like this:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://dto.shared.auth.appl.com"
xmlns:Q1="http://dto.shared.auth.appl.com"
xmlns:Q3="http://dto.common.appl.com" elementFormDefault="qualified">
<xs:import namespace="http://dto.common.appl.com"
schemaLocation="shared-environment.xsd" />
.........
.........
.........
The WS-Adapter is defined this way:
#EnableWs
#Configuration
public class BackendServerConfig extends WsConfigurerAdapter {
#Bean
ServletWebServerFactory servletWebServerFactory(){
return new TomcatServletWebServerFactory();
}
#Bean
public ServletRegistrationBean<MessageDispatcherServlet> messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean<MessageDispatcherServlet>(servlet, "/authentication/*");
}
#Bean(name = "authentication")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema authenticationSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("SharePort");
wsdl11Definition.setLocationUri("/authentication");
wsdl11Definition.setTargetNamespace("http://dto.shared.auth.timetracker.appl.com");
wsdl11Definition.setSchema(authenticationSchema);
return wsdl11Definition;
}
#Bean
public XsdSchema authenticationSchema() {
return new SimpleXsdSchema(new ClassPathResource("auth-attributes.xsd"));
}
I'm not really familiar with WSDL. The JAXB source generation from the XSDs is fine but the WSDL resolution fails. I't seems I need a method to tell the WSDL-building mechanism where to retrieve the imported XSDs.

The "DefaultWsdl11Definition" has got the method setSchemaCollection() to register multiple XSD-definitions. I used this method instead of setSchema - this helped - at least a bit. The error message has gone and the Soap-requests are answered correctly.
Only, when "adding" a new project to SoapUI, the client does not create automatically requests - for whatever reason - this only works with "import" from webserver.
The WS-Configuration now looks like this:
#EnableWs
#Configuration
public class BackendServerConfig extends WsConfigurerAdapter {
#Bean
ServletWebServerFactory servletWebServerFactory(){
return new TomcatServletWebServerFactory();
}
#Bean
public ServletRegistrationBean<MessageDispatcherServlet> messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean<MessageDispatcherServlet>(servlet, "/authentication/*");
}
#Bean(name = "authentication")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema authenticationSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("SharePort");
wsdl11Definition.setLocationUri("/authentication");
wsdl11Definition.setTargetNamespace("http://dto.shared.auth.app.com");
wsdl11Definition.setSchemaCollection(schemaCollection());
return wsdl11Definition;
}
private XsdSchemaCollection schemaCollection() {
CommonsXsdSchemaCollection commonsXsdSchemaCollection = new CommonsXsdSchemaCollection(
new ClassPathResource("auth-attributes.xsd"),
new ClassPathResource("shared-environment.xsd"));
commonsXsdSchemaCollection.setInline(true);
return commonsXsdSchemaCollection;
}

Related

Vert.x Service Proxies: Just after I change service methods from returning Future<T> to Uni<T> of Smallrye Mutiny, the code generation failed

I've sucessfully generated service proxies for service having methods returning Future<T>,
but just after I changed those methods to return Uni<T> according to API Translation - Smallrye Mutiny Vert.x bindings,
when I try to execute mvn clean compile it always tells me this error message :
Could not generate model for com.example.beers.BarmanService#giveMeAStaticBeer(java.lang.String): Proxy methods must have void or Fluent returns
I would need your help to enlighten me how to fix it.
I put those codes on GitHub, and these are some critical ones:
//BarmanService.java
#VertxGen
#ProxyGen
public interface BarmanService {
Uni<Beer> giveMeAStaticBeer(String customerName);
Uni<Integer> getMyBill(String customerName);
Uni<Void> payMyBill(String customerName);
static BarmanService createProxy(Vertx vertx, String address) {
return new BarmanServiceVertxEBProxy(vertx, address);
}
}
//BarmanServiceImpl.java
public class BarmanServiceImpl implements BarmanService {
Map<String, Integer> bills;
public BarmanServiceImpl() {
this.bills = new HashMap<>();
}
#Override
public Uni<Beer> giveMeAStaticBeer(String customerName) {
Beer beer = new Beer("Workshop River Stout", "English Stout", 5);
return Uni.createFrom().item(() -> beer);
}
#Override
public Uni<Integer> getMyBill(String customerName) {
return Uni.createFrom().item(() -> bills.get(customerName));
}
#Override
public Uni<Void> payMyBill(String customerName) {
bills.remove(customerName);
System.out.println("Removed debt of " + customerName);
return Uni.createFrom().voidItem();
}
}
//package-info.java
#ModuleGen(groupPackage = "com.example", name = "beers")
package com.example.beers;
import io.vertx.codegen.annotations.ModuleGen;
<!-- //pom.xml -->
<dependencies>
<!-- // ... -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-codegen</artifactId>
<classifier>processor</classifier>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-service-proxy</artifactId>
</dependency>
<!-- // ... -->
<dependency>
<groupId>io.smallrye.reactive</groupId>
<artifactId>smallrye-mutiny-vertx-core</artifactId>
<version>2.30.1</version>
</dependency>
<dependency>
<groupId>io.smallrye.reactive</groupId>
<artifactId>vertx-mutiny-generator</artifactId>
<version>2.30.1</version>
</dependency>
<!-- // ... -->
</dependencies>
PS In the beginning, when I generated service proxies for service having methods returning Future<T>, there is a generated class returning Uni<T>, but I have no idea how to use it:
package com.example.mutiny.beers;
#io.smallrye.mutiny.vertx.MutinyGen(com.example.beers.BarmanService.class)
public class BarmanService {
public static final io.smallrye.mutiny.vertx.TypeArg<BarmanService> __TYPE_ARG = new io.smallrye.mutiny.vertx.TypeArg<>( obj -> new BarmanService((com.example.beers.BarmanService) obj),
BarmanService::getDelegate
);
private final com.example.beers.BarmanService delegate;
public BarmanService(com.example.beers.BarmanService delegate) {
this.delegate = delegate;
}
public BarmanService(Object delegate) {
this.delegate = (com.example.beers.BarmanService)delegate;
}
/**
* Empty constructor used by CDI, do not use this constructor directly.
**/
BarmanService() {
this.delegate = null;
}
public com.example.beers.BarmanService getDelegate() {
return delegate;
}
#CheckReturnValue
public io.smallrye.mutiny.Uni<com.example.beers.Beer> giveMeAStaticBeer(String customerName) {
return io.smallrye.mutiny.vertx.UniHelper.toUni(delegate.giveMeAStaticBeer(customerName));}
public com.example.beers.Beer giveMeAStaticBeerAndAwait(String customerName) {
return giveMeAStaticBeer(customerName).await().indefinitely();
}
public void giveMeAStaticBeerAndForget(String customerName) {
giveMeAStaticBeer(customerName).subscribe().with(io.smallrye.mutiny.vertx.UniHelper.NOOP);
}
// ...
public static com.example.mutiny.beers.BarmanService createProxy(io.vertx.mutiny.core.Vertx vertx, String address) {
com.example.mutiny.beers.BarmanService ret = com.example.mutiny.beers.BarmanService.newInstance((com.example.beers.BarmanService)com.example.beers.BarmanService.createProxy(vertx.getDelegate(), address));
return ret;
}
public static BarmanService newInstance(com.example.beers.BarmanService arg) {
return arg != null ? new BarmanService(arg) : null;
}
}
I just figured it out by myself. About to change service methods from returning Future<T> to Uni<T>,
The wrong apporach I did:
Edit package-info to remove useFutures = true
Edit service interfaces and change returning types
Edit service implimentations and change returning types, also change logic
Edit verticles to handle Uni<T> returned from service
And it turned out that the first three steps I did is unnecessary,
the suitable approach is:
Wrap vertx:
io.vertx.mutiny.core.Vertx mutinyVertx = new io.vertx.mutiny.core.Vertx(vertx);
Change the use of service interface to the generated one
import com.example.mutiny.beers.BarmanService;
Use the wrapped vertx:
BarmanService barmanService = BarmanService.createProxy(mutinyVertx, "beers.services.myapplication");
Edit verticles to handle Uni<T> returned from service
My problem has been solved, but I am not sure is it a good apporach to manually wrap the vertx on the MainVerticle launched by io.vertx.core.Launcher: io.vertx.mutiny.core.Vertx mutinyVertx = new io.vertx.mutiny.core.Vertx(vertx);, any suggestions guys?

StaxEventItemWriter XML Header

I am using StaxEventItemWriter for writing to an XML file. I am looking out to set standalone attribute on the xml tag to true. Is there any option to set it.
<?xml version="1.0" encoding="UTF-8" standalone="true"?>
You can extend StaxEventItemWriter and override the startDocument method. Here is an example:
#Bean
public StaxEventItemWriter<Person> itemWriter() {
StaxEventItemWriter<Person> itemWriter = new StaxEventItemWriter<Person>() {
#Override
protected void startDocument(XMLEventWriter writer) throws XMLStreamException {
writer.add(createXmlEventFactory().createStartDocument(DEFAULT_ENCODING, DEFAULT_XML_VERSION, true));
writer.add(xmlEventFactory.createStartElement(getRootTagNamespacePrefix(), getRootTagNamespace(), getRootTagName()));
}
};
// TODO set other properties on the writer
return itemWriter;
}

Rest assured multipart is null in rest controller

I'm building rest-assured test for rest controller.
Rest-assured test:
#Test
fun saveFileReturnsFileKeyAndStatusCreated() {
given()
.multiPart("file", File("d:/2.txt"))
.multiPart("fileDescription", "...file description here...")
.multiPart("fileExtension", ".txt")
.`when`()
.post("/file")
.then()
.statusCode(HttpStatus.CREATED.value())
.body(notNullValue<String>(String::class.java))
}
Rest controller method:
#RestController
#RequestMapping(produces = arrayOf(MediaType.APPLICATION_JSON_UTF8_VALUE))
class ClientActionsController(private var clientActionsService: ClientActionsService) {
#PostMapping(value = "/file", consumes = arrayOf(MediaType.MULTIPART_FORM_DATA_VALUE))
fun saveFile(request: HttpServletRequest): ResponseEntity<String> {
println(request.getPart("fileDescription"))
println(request.getPart("fileExtension"))
println(request.getPart("file"))
return ResponseEntity(clientActionsService.saveFile(request), HttpStatus.CREATED)
}
}
Real code works fine, but when I start the test all the parts in request are null.
What might be the cause for not receiving rest-assured's multiparts in rest controller's HttpServletRequest?
Spring Boot 1.5.8, rest-assured 3.0.5
The reason your file is null, because in your test configuration class, you need to have #bean for MultipartFileResolver.
Something like this:
#Bean
public MultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}

GWT : Getting a 404 error when unit testing RequestBuilder

I use the GWT RequestBuilder, and for testing purposes, I'd like to load a json file in the server.
It works perfectly with the DevMode, but throw a 404 error with GWTTestCase.
With RPC, there is a fix adding <servlet path=".." class="..."/>, but what can I do with static content ?
I could easily use #TextResource, but it's not the goal of my UnitTest (which is in fact a functionnal test)
Static resources can be bundled with a module by putting them in the module's public path.
I used (once again) Thomas's answer to resolve the problem. My module is io.robusta.fora.comments.Comment.gwt.xml and I've put my user.json file in the io.robsuta.fora.comments.resources package.
I had so to add in Comment.gwt.xml file : <public path="resources"/>
Then the GWTTestCase is straightforward :
public class GwtRestClientTest extends GWTTestCase{
#Override
public String getModuleName() {
return "io.robusta.fora.comments.Comments";
}
public void testGET(){
String base = GWT.getModuleBaseURL();
System.out.println(base); //-> http://192.168.0.10:53551/io.robusta.fora.comments.Comments.JUnit/
GwtRestClient client = new GwtRestClient(base); //base url
AsyncCallback<String> cb = new AsyncCallback<String>() {
#Override
public void onSuccess(String result) {
System.out.println(result);//->{id:1,email:"jo#robusta.io"}
finishTest();
}
#Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
};
client.GET("user.json", null, cb);//fetch my json file with no params
delayTestFinish(3000);
}
}

Reading xls file in gwt

I am looking to read xls file using the gwt RPC and when I am using the code which excecuted fine in normal file it is unable to load the file and giving me null pointer exception.
Following is the code
{
{
import com.arosys.readExcel.ReadXLSX;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import org.Preview.client.GWTReadXL;
import java.io.InputStream;
import com.arosys.customexception.FileNotFoundException;
import com.arosys.logger.LoggerFactory;
import java.util.Iterator;
import org.apache.log4j.Logger;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
*
* #author Amandeep
*/
public class GWTReadXLImpl extends RemoteServiceServlet implements GWTReadXL
{
private String fileName;
private String[] Header=null;
private String[] RowData=null;
private int sheetindex;
private String sheetname;
private XSSFWorkbook workbook;
private XSSFSheet sheet;
private static Logger logger=null;
public void loadXlsxFile() throws Exception
{
logger.info("inside loadxlsxfile:::"+fileName);
InputStream resourceAsStream =ClassLoader.getSystemClassLoader().getSystemResourceAsStream("c:\\test2.xlsx");
logger.info("resourceAsStream-"+resourceAsStream);
if(resourceAsStream==null)
throw new FileNotFoundException("unable to locate give file");
else
{
try
{
workbook = new XSSFWorkbook(resourceAsStream);
sheet = workbook.getSheetAt(sheetindex);
}
catch (Exception ex)
{
logger.error(ex.getMessage());
}
}
}// end loadxlsxFile
public String getNumberOfColumns() throws Exception
{
int NO_OF_Column=0; XSSFCell cell = null;
loadXlsxFile();
Iterator rowIter = sheet.rowIterator();
XSSFRow firstRow = (XSSFRow) rowIter.next();
Iterator cellIter = firstRow.cellIterator();
while(cellIter.hasNext())
{
cell = (XSSFCell) cellIter.next();
NO_OF_Column++;
}
return NO_OF_Column+"";
}
}
}
I am calling it in client program by this code:
final AsyncCallback<String> callback1 = new AsyncCallback<String>() {
public void onSuccess(String result) {
RootPanel.get().add(new Label("In success"));
if(result==null)
{
RootPanel.get().add(new Label("result is null"));
}
RootPanel.get().add(new Label("result is"+result));
}
public void onFailure(Throwable caught) {
RootPanel.get().add(new Label("In Failure"+caught));
}
};
try{
getService().getNumberOfColumns(callback1);
}catch(Exception e){}
}
Pls tell me how can I resolve this issue as the code runs fine when run through the normal java file.
Why are using using the system classloader, rather than the normal one?
But, If you still want to use then look at this..
As you are using like a web application. In that case, you need to use the ClassLoader which is obtained as follows:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
This one has access to the all classpath paths tied to the webapplication in question and you're not anymore dependent on which parent classloader (a webapp has more than one!) has loaded your class.
Then, on this classloader, you need to just call getResourceAsStream() to get a classpath resource as stream, not the getSystemResourceAsStream() which is dependent on how the webapplication is started. You don't want to be dependent on that as well since you have no control over it at external hosting:
InputStream input = classLoader.getResourceAsStream("filename.extension");
The location of file should in your CLASSPATH.