Axis2 error: Invalid white space character (0x4) in text to output - java

I have created a Java client to interact with a SOAP webservice using Axis2 (1.7.6) as code generator. The problem is with some inputs the client is throwing an exception with the message:
org.apache.axis2.AxisFault: Invalid white space character (0x4) in text to output (in xml 1.1, could output as a character entity)
It seems the serialiser is hitting some chars considered invalid to XML spec. I have seen that problem around but no definitive answer or the fix. I'm not using Spring or any other dependency injection framework, it's a standalone application, so I need to configure the inners of Axis2 by hand.
Any ideas on how to fix/configure the client properly?

After some research I found this behaviour is due to one default setting of the lib Woodstox (Axis2 dependency), that uses the class com.ctc.wstx.api.InvalidCharHandler.FailingHandler as default implementation of the interface com.ctc.wstx.api.InvalidCharHandler, used inside com.ctc.wstx.sw.XmlWriter and invoked in the serialisation process. This means: when the component hits characters considered invalid to XML, it’ll throw an error.
Woodstox provides another implementation of the interface com.ctc.wstx.api.InvalidCharHandler, the one called com.ctc.wstx.api.InvalidCharHandler.ReplacingHandler that instead of throwing errors will replace those chars for something else. But how to do that?
The class com.ctc.wstx.stax.WstxOutputFactory inside Woodstox contains several configurations, one of them being the invalid char handler. Though, it's not configurable by some magic system wide property, instead, by the method com.ctc.wstx.stax.WstxOutputFactory#setProperty, that takes as arguments one string and one object.
So first, you'll have to extend that factory and set the property com.ctc.wstx.outputInvalidCharHandler with an instance of com.ctc.wstx.api.InvalidCharHandler.ReplacingHandler that takes as argument the char you want to replace the invalid ones with. Like this:
package my.package;
import com.ctc.wstx.stax.WstxOutputFactory;
public class MyWstxOutputFatory extends WstxOutputFactory {
public MyWstxOutputFatory() {
setProperty(
com.ctc.wstx.api.WstxOutputProperties.P_OUTPUT_INVALID_CHAR_HANDLER,
new com.ctc.wstx.api.InvalidCharHandler.ReplacingHandler(' '));
}
}
The second, trickiest and undocumented step is how to register your implementation as the factory Woodstox'll use. You'll have to create a file named META-INF/services/javax.xml.stream.XMLOutputFactory simply containing the name of your factory, in this case, the string:
my.package.MyWstxOutputFatory
Place this file in such a way it's included in your project's resulting jar. In my case I placed like: src/main/resources/META-INF/services/javax.xml.stream.XMLOutputFactory.
And you're done!

Related

Using Lombok's SuperBuilder with Hibernate Validator (jakarta.validation.x) annotation on a container type leads to "Type mismatch"

I have a class ActivitiesModel which uses Lombok's SuperBuilder.
import jakarta.validation.NotBlank;
// other imports and statements omitted for brevity.
#Data
#SuperBuilder
#NoArgsConstructor
public class ActivitiesModel {
public static final String ACTIVITIES_NOT_NULL_MESSAGE = "Activities cannot be null";
public static final String ACTIVITY_NOT_BLANK_MESSAGE = "Activity cannot be blank";
#NotNull(message = ACTIVITIES_NOT_NULL_MESSAGE)
private List<#NotBlank(message = ACTIVITY_NOT_BLANK_MESSAGE) String> activities;
}
I am using this builder to create an object of ActivitiesModel, and then validating it using Hibernate's Validator interface:
// Somewhere else in the application.
// Create an object using the builder method.
ActivitiesModel activitiesModel = ActivitiesModel.builder()
.activities(List.of("hello", "world")) // <----- Point A
.build();
// Validate the object using Hibernate's validator.
validator.validate(activitiesModel);
However, running this code gives me the following error:
java.lang.Error:
Unresolved compilation problem:
Type mismatch: cannot convert from List<String> to List<E>
The stack trace seems to be pointing at Point A.
I have tried the following approaches:
Replacing the #SuperBuilder with #Builder and #AllArgsConstructor.
Replacing the message attribute with a string literal instead of a static final variable, i.e:
private List<#NotBlank(message = "Activity cannot be blank") String> activities;
1st approach seems to fix this error, however, it's not something I can use as I need to extend the builder functionality to a subclass of ActivitiesModel. Also, this issue is also present in another abstract class, so the super builder functionality for parent classes is definitely required.
2nd approach also works in solving the error. However, going with it is a bit problematic because I then need to have the same message string in the validation test for this model class, which is something I would like to avoid as it duplicates the string.
Another thing to note is that this error only seems to occur in the presence of an annotation on the generic type parameter of the container, which is NotBlank in this case. It is not influenced by any annotations which are present directly on the field itself (NotNull in this case).
So, all in all, these are the questions that I would like to get some answers to:
Somehow, Lombok is able to figure out the types in case of a string literal but not in case of a static final String. Why is that?
Am I going about this totally wrong? The problem occurs because I'm trying to store the message string in a variable, and I'm trying to re-use the same variable at two places: the annotation's message attribute, and in the validation test for the model class. Should I not be checking for the presence of the message in my validation tests, but be checking for something else instead?
For anyone who comes across this later on, the research for this issue has led me to believe that comparing message strings in tests is not the way to go about writing validation test cases. Another downside to this approach is that you might have different validation messages for different locales. In that case, the message string itself might be a template e.g. my.message.key with its values in a ResourceBundle provided to Hibernate, i.e. files such as ValidationMessages.properties and ValidationMessages_de.properties.
In such a scenario, you could compare message for one locale in your validation test case, however, a better approach might be to check the annotation and the field for which the validation has failed. We can get both of these pieces of information via the ConstraintViolation and subsequently the ConstraintDescriptor types, provided by Hibernate. This way we can circumvent checking the message itself, but rely on the actual validation annotation which has failed.
As for the solution to this question, it seems it was a build cache issue. Cleaning maven's build cache results in this code working perfectly fine, but VSCode still seems to have an issue. For now, I will choose to ignore that.

No measurement ServiceProvider found

I'm researching the unit of measure open source library, and the maven dependency I use is:
<dependency>
<groupId>tec.units</groupId>
<artifactId>unit-ri</artifactId>
<version>1.0.2</version>
</dependency>
which implements the JSR-363. When I try to use it as below:
ServiceProvider provider = ServiceProvider.current();
The result is:
Exception in thread "main" java.lang.IllegalStateException: No measurement ServiceProvider found.
Could anybody tell me what is wrong?
I faced with the same problem using the measure library in the java bean forms while opening beans within the Netbeans IDE. This trick works for me:
import javax.measure.spi.ServiceProvider;
import tec.units.ri.spi.DefaultServiceProvider;
private ServiceProvider serviceProvider;
try {
serviceProvider = ServiceProvider.current();
} catch ( IllegalStateException e ) {
serviceProvider = new DefaultServiceProvider();
}
So, I have looked into the class ServiceProvider to see what the current() method does:
https://github.com/unitsofmeasurement/unit-api/blob/master/src/main/java/javax/measure/spi/ServiceProvider.java
You can see it uses the ServiceLoader to return a value. If you look at the documentation of the ServiceLoader you will see that you need a config file:
https://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html
A service provider is identified by placing a provider-configuration file in the resource directory META-INF/services. The file's name is the fully-qualified binary name of the service's type. The file contains a list of fully-qualified binary names of concrete provider classes, one per line. Space and tab characters surrounding each name, as well as blank lines, are ignored. The comment character is '#' ('\u0023', NUMBER SIGN); on each line all characters following the first comment character are ignored. The file must be encoded in UTF-8.
For everyone who may need to use this library. It is strange but after i change the maven dependency version from 1.02 to 1.01,no other change,it works fine. So , this should be a bug of this version...

How do I debug what's wrong when the Endpoints framework stops generating the WEB-INF/*.api-file?

Given a Google Cloud Endpoints project in Eclipse with the servlet-class annotated with #Api(name="helloworld"), the Endpoints framework generates a file named war/WEB-INF/helloworld-v1.api when the project compiles successfully. Sometimes this file is not generated even if there are no compilation errors though - only what I will call "GAE Endpoints code convention errors".
Example - working:
public class TestEntity {
public String Text;
public TestEntity(String text){
Text = text;
}
}
#ApiMethod
public TestEntity getTestEntity(){
return new TestEntity("Hello world");
}
Example - NOT working:
// The TestEntity-class is unchanged
#ApiMethod
public TestEntity getTestEntity(String input){
return new TestEntity("Hello world");
}
The problem with the latter example is that I take a String parameter as input without annotating it with #Named. I know that in this example, but there might be other cases where this is not so obvious.
Is there anywhere where I can read some sort of error log on why the .api file is not generated?
Although I am a fan of code by convention, it really takes the programming efficiency a step back if I cannot get feedback on what I do wrong. Eclipse provides compiler error feedback. The Google Cloud Endpoints Framework should provide Code-By-Convention-Rule-Breaking feedback.
There isn't currently good logging or error messaging when code generation fails, though it's one of the (if not most) requested features. In the interim, here's a list of the common failure cases:
The return type is invalid. Return types must be objects conforming to JavaBean conventions, and types like Object, String, and Integer are not allowed.
One or more argument types are invalid. Methods may accept at most one object in the POST body, and this object should also conform to JavaBean conventions. Methods may accept zero or more arguments via the query string (using the #Named annotation) and these must be scalar types (e.g. String, Integer).
An API, method, or parameter has an invalid name. APIs, methods, and parameters should be named to match the following regular expression: [a-z]+[A-Za-z0-9]*. Convention also suggests using lowerCamelCase for naming (though alllowercase is allowed).

GRAILS: method for permalink/slug generation?

Does anybody have a quick method to generate slugs and permalinks in Grails 1.3.7/2.0.0.RC1?
The main restriction: this method should work with non-latin characters.
Russian/bulgarian cirillic, deutsch umlauts etc...
Any suggestions ?
Grails 2.0.0.RC1
From the 2.0.0.RC1 docs:
Link Generation API
A general purpose LinkGenerator class is now available that is usable
anywhere within a Grails application and not just within the context
of a controller. For example if you need to generate links in a
service or an asynchronous background job outside the scope of a
request:
LinkGenerator grailsLinkGenerator
def generateLink() { grailsLinkGenerator.link(controller:"book", action:"list") }
Although it's not stated explicitly, I assume the reference to grailsLinkGenerator is obtained via dependency injection
Grails 1.3.7
You can use either the createLink or resource tags to generate links. If you're generating permalinks, I assume you'll want these to be absolute URLs. If so, you'll need to use either the absolute or base attribute when using these tags.
If you use the absolute attribute, be sure to set the value of grails.serverURL in Config.groovy
Link Permanence
The text above describes how to generate links to resources in a Grails application, but doesn't say anything about how to make these links permanent. AFAIK, the link to a resource will always remain the same as long as you don't change anything that is used in the URL mapping scheme (as defined in UrlMappings.groovy)
By default the URL mapping scheme uses
the resource's ID
the controller name
the action name
So if you never change these for the links of interest, you should be good.
As easy as:
title.replaceAll("[\\W]+", "-")
That makes it.

How should I use Stax2 Validation API against a W3 Schema

I am using com.ctc.wstx.stax.WstxOutputFactory to generate XML.
I am running wstx-asl-3.2.4
I need to start validating the generated XML against a W3 Schema.
When I create an instance of org.codehaus.stax2.validation.XMLValidationSchemaFactory like this
private final static XMLValidationSchemaFactory xsdFact=
XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA);
I get the error
javax.xml.stream.FactoryConfigurationError: No XMLValidationSchemaFactory implementation class specified or accessible (via system property 'org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c', or service definition under 'META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c')
at org.codehaus.stax2.validation.XMLValidationSchemaFactory.newInstance(XMLValidationSchemaFactory.java:208)
at org.codehaus.stax2.validation.XMLValidationSchemaFactory.newInstance(XMLValidationSchemaFactory.java:98)
I can see that woodstox is bundled with a DTD parser only.
I found this article
which contains the unhelpful instruction
Get an instance of XMLValidationSchemaFactory that knows how to parse schemas of the type you need (RelaxNG == rng for this example).
I have been looking at the Sun Multi-Schema XML Validator which is supposed to contain the bits necessary to bolt on to the XMLSchemaValidation factory.
It looks like I might be able to use com.sun.msv.reader.xmlschema.XMLSchemaReader
to write my own instance of XMLValidationSchemaFactory and get it to work this way.
My question is; do I really have to do this, or is there a pre-existing w3c schema factory that I have failed to find?
Perhaps it would be simpler just to validate the XML after I have generated it.
What are the views on this ?
I've upgraded to Woodstox 4.0.8, W3CSchemaFactory comes bundled and its all good.

Categories