Using a SOAP artifact in Java - java

I've been searching all over and I can't find a simple example for this. I need to call a Web service from my Java application using SOAP. I've run the utility to create all the Java artifacts from the WSDL. Let's say one is called "Customer", and these are the first few lines:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Customer", propOrder = { "id" })
public class Customer {
I assume that I start by creating a new Customer object and setting all the attributes I need. What I need to know is how to take that object and pass it to the service as a SOAP envelope(?). I also have artifacts for submit, like "SubmitCustomer", but again I'm not sure how to take my Customer object and keep going with it.
I'm sure this is a basic question, but all I've been able to find in my searches are examples of creating your own XML, or basic "how to get started with SOAP", or how to generate artifacts, but that's all. If someone can point me to a good resource, that would be great.

Among generated classes must be one extends javax.xml.ws.Service.
Look through this class to find a method annotated with #WebEndpoint.
Open file with definition of return type of this method.
There you will find methods correspond to WSDL operations.

Related

Swagger/Openapi-Annotations: How to produce allOf with $ref?

I'm generating Rest endpoints including adding Openapi/Swagger annotations to the generated code.
While it works quite well with basic types, I have some problems with custom classes.
Right now I have a lot of duplicate schema entries for the custom classes (using #Schema(implementation = MyClass.class)) but at least the needed information is there. However I'd like to find a way to remove the duplicate schema entries while retaining the additional information.
On a github-issue discussing the $ref and lack of sibling properties I found an example how you would write it manually in yaml in order to get the result I'm looking for, however I can't figure out how to set the annotations to produce it.
This is how I think the annotation should look like if I follow the example (just to be on the safe side it is added to both the getter and the setter):
import io.swagger.v3.oas.annotations.media.Schema;
...
public class SepaPaymentRequest {
...
#Schema(name = "w307BetrBeg", description = "BETRAG BEGUENSTIGTER ", allOf = { com.diesoftware.services.utils.Betrag.class }, required = true)
public void setW307BetrBeg(final Betrag w307BetrBeg) {
this.w307BetrBeg = w307BetrBeg;
}
...
}
However what I get when I fetch the openapi.yaml (snippet):
w307BetrBeg:
$ref: '#/components/schemas/Betrag'
What I'd like to have:
w307BetrBeg:
title: 'Betrag'
description: 'BETRAG BEGUENSTIGTER'
allOf:
- $ref: '#/components/schemas/Betrag'
Any hints are more than welcome.
I haven't found a way to do it using annotations, i.e. by annotating the class.
I think it's possible to do, by:
Creating a model
Injecting the model using a ModelConverter
When I say "a model" I mean an instance of io.swagger.v3.oas.models.media.Schema.
In particular I think you'd want to create and inject a io.swagger.v3.oas.models.media.ComposedSchema instance, which supports allOf.
Doing this (i.e. creating model instances) isn't very different from hand-writing the YAML.
Another possibility -- which I haven't tried -- might be to write a slightly different ModelConverter, which you install into the chain of converters. Then, intercept calls to resolve which return a SchemaObject whose name is Betrag, and (sometimes?) replace that with a ComposedSchema instance which uses allOf.

Class cast exception when invoking JBPM process through REST API and passing in custom object

I have downloaded JBPM business application template from http://start.jbpm.org. I have added a custom data model in the model project and gave reference to the same in the kjar and service projects. I imported the project into the controller and then created a process with the custom object being one of the process input variables.
Then I fetched the bpmn process into code through git pull process as per documentation. The project got built and deployed successfully. However, when I try to create the process instance, it is giving me a class cast exception. My data model implements the java.io.Serializable interface and has a public constructor.
I am not able to find a solution in the documentation regarding this. Any help or pointers to a solution would help.
I have tried changing the input JSON formats which I post to create the process instances.
{
"employee": {
"lastName": "Sample1",
"firstName": "Sample2",
"employeeId": 1
}
}
I tried adding in type information in the JSON, but it did not work.
The REST API is being called through POSTMAN utility and there is no client code written as of now.
Unable to create response: [soap-client-kjar.OtherProcess:9 - LogAndSetupData:2] -- java.util.LinkedHashMap cannot be cast to com.test.Employee
The user-defined class definition must implement a no-arg constructor.
The class definition must be included in the deployment jar (kjar) of the deployment that the command (request) is sent to.
The class must implement java.io.Serializable.
These classes must also be annotated with one of the following type annotations: org.kie.api.remote.Remotable.

Problems searching for annotated classes using Reflections API

I'm having a very difficult time using the Reflections API to find classes that are annotated with a custom annotation at runtime. The ultimate goal is to find all classes in the project that are annotated with my custom #Job annotation, collect them, and allow each of them to be run from one location without adding each one to the page manually. However, I'm finding it extremely difficult to get the initial search to work correctly, so I cannot move on with my project.
My current approach is to use:
Reflections reflections = new Reflections(new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage("jobs"))
.setScanners(new TypeAnnotationsScanner())
.filterInputsBy(new FilterBuilder().includePackage("jobs")));
Set<Class<?>> jobs = reflections.getTypesAnnotatedWith(Job.class);
where "jobs" is the package containing all of the job classes that I am searching for, which will be annotated with the custom #Job annotation. "jobs" is a base package in my project, but the overall url on my machine looks something like ".../(project)/app/jobs". This setup results in one url being searched, which is ".../(project)/app/" with the additional filter "+jobs.*" in the configuration object. This seems like it is working correctly, but clearly something is wrong because I do not get any classes in the set.
If it matters, the annotation is coded as:
package jobs;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface Job {
String description();
}
The annotation class is located within the same "jobs" package as the job classes I am searching for. An example of a job definition with the annotation included is:
package jobs;
#Job(description = "Description of what the job will do")
public class ExampleJob extends MasterJob {...}
I cannot find what I need to change in order to get this search to function as intended. Thanks for the help, and please let me know if I can clarify anything further.
EDIT: I believe the problem is associated with how the Play Framework loads its classes. Fortunately, the framework provides its own annotation search function, which I used instead. According to a comment, the code I have listed here will work, given that you have all the dependencies to run it. Feel free to use it as a template and let me know if it works for you as well.

How to make changes in marshalled output in Java web service client

I am trying to interact with a third party web service, who requires me to send a security token as a part of each request. The token is a node by itself, and I acquire it from the response of an initial call.
The web service endpoint is dotNet, and I have a Java client.
Apparently, the server side expects me to send the security token exactly like it was provided to me: literally the same string: so it won't do if its content has a different size, order, etc.
So, in SoapUI, everything works fine. There is a token in the response of the initial 'startSession' call, which I copy into the request of a next call.
But in Java (I tried JAX-WS and CXF generated code, both rely on JAXB) it doesn't work. I receive the token as an object after it is unmarshalled, and I use this object in the next call.
When marshalled and send, it is missing a namespace attribute in a subnode. The server side says it won't continue because the token is incorrect.
So, by using JAXB outbound logical handler functionality, I am able to add the missing namespace without any problems in the DOM source (I was also able to achieve this with a CXF interceptor).
The problem now is, that the attributes, when marshalled, are ordered in such a way that the result still not matches the provided token as it was before it was unmarshalled. Alhough it should not matter, the order of these attributes is crucial.
I have no idea how to solve this, unless it is possible to actually modify the output XML string. I even tried a dirty hack by removing all attributes from the subnode and replacing them with one attribute that visually looks the same; but then the outer two double quotes become single quotes...
I hope anyone has an idea. Because I have none.
Cheers.
UPDATE:
I should have mentioned that the attributes in question are namespace(d) attributes. The node should look like this:
<HawanedoSessionInfo xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.thecompany.com/Hawanedo/Business/v2.0c">
However, after using outbound JAXB handler to add the missing xmlns="...", my result looks like this:
<HawanedoSessionInfo xmlns="http://schemas.thecompany.com/Hawanedo/Business/v2.0c" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
In the HawanedoSessionInfo class, I used XmlType.proporder and #XmlAttribute like so:
#XmlType(name = "HawanedoSessionInfo", propOrder = {
"xsd",
"xsi",
"xmlns",
and some other non-attribute sub-elements..
private String xsd;
private String xsi;
private String xmlns;
#XmlAttribute(ns="http://schemas.thecompany.com/Hawanedo/Business/v2.0c")
public String getXsd() {
return xsd;
}
public void setXsd(final String xsd) {
this.xsd = xsd;
}
#XmlAttribute(ns="http://schemas.thecompany.com/Hawanedo/Business/v2.0c")
public String getXsi() {
return xsi;
}
public void setXsi(final String xsi) {
this.xsi = xsi;
}
#XmlAttribute
public String getXmlns() {
return xmlns;
}
public void setXmlns(final String xmlns) {
this.xmlns = xmlns;
}
So apparently the proporder option does not help in this case?
UPDATE 2:
Like I wrote in my answer, it now works. Based on this LINK,
in the HawanedoSessionInfo class I added:
#XmlCustomizer(HawanedoSessionInfoCustomizer.class)
I created the customizer class exactly as described in the linked page, and I added the jaxb.properties.
So I did two things:
1) I added my attributes to (the top of the already existing) propOrder attribute. I added the attributes as instance variables and created the getters/setters. I annotated the getters with XmlAttribute.
2) I implemented the XmlCustomizer solution.
Now comes the strange part. According to Fiddler, the order of the attributes is still not changed! But I must stress that this is now working, ONLY after implementing the Customizer. What is happening here? :)
So in principle you cannot control order of attributes in a standard way, but ....
Depending on jaxb /java version the order can be determined by alphabetical order of the names, the order of declaration.
You could try in your code if a) moving the fields around changes anything, b) renaming the fields (the XMLAttribute than have to map to original name).
If you are lucky, it will work. But of course it is a hack and will work till next jaxb/java update.
The JAXB providers (the actuall implementation can have extra features), that can be used to customized the marshalling process). For example I found that: https://community.oracle.com/thread/977397 abut eclipselink.
I am sure there was a way of intercepting the soap body before it is send or governing the data serialization before it is send. I can think how it was called but try to google the jaxws client customization. If you capture the whole soap message simple xslt transforamation could fix the attributes order.
I feel your pain. The whole point of using xml, jaxws and such is to make our life easier and then someone providers decide not to follow standards and you end up with a mess that you were trying to clean for few days. Good luck and maybe try to contact xml gurus from Eclipse Moxy
I am so happy right now, because I got it working and it only cost me a full week to do so...:) With help of #Zielu, I was pointed to this link with the EclipseLink XMLCustomizer solution as suggested by Blaise Doughan: XMLCustomizer solution
I took the code in my original question (underneath 'UPDATE') and added the exact solution as suggested. Not sure if it is all necessary, but it works. Thanks guys.
It's possible you can control the order by using,
#XmlType (propOrder={"prop1","prop2",..."propN"})

Jackson - Deserializing to a Different Type

Using Jackson, how can I have JSON serialized/deserialized by one application using one set of classes, but have another application deserialize the same JSON and load different implementations of those classes?
I have a (Spring MVC) web application that allows users to define steps in a script, that in turn will be executed in a client application. Steps might be things like ShowDialogStep, with properties like dialogText, or WaitStep with a property of duration.
The client application will load collections of steps from the server. However, the classes instantiated by the client need to have execution-specific functionality like execute(), which in the case of WaitStep will keep a track of how far through waiting it is. Clearly the server-side application never needs know about this, and in less trivial examples the execute/update logic of a steps involves all manner of client-specific dependencies.
So, to recap I need:
The server application to map the 'prototype' classes to JSON;
The client application to read the same JSON but instantiate execution-specific classes instead of the 'prototype' ones.
Would this be something that could be configured on the client-side mapper, perhaps if the JSON was serialized using relative class names (rather than fully-qualified) then the deserializer could be configured to look in a different package for the implementations with execution logic in them?
You can use this approach:
On the server side:
#JsonTypeInfo(use=JsonTypeInfo.Id.NAME,
include=JsonTypeInfo.As.PROPERTY, property="#type")
class Prototype {
...
}
objectMapper.registerSubtypes(
new NamedType(Prototype.class, "Execution"),
...
);
then it will serialize a Prototype instance and add a type of bean:
{
"#type" : "Execution",
...
}
on the client-side:
#JsonTypeInfo(use=JsonTypeInfo.Id.NAME,
include=JsonTypeInfo.As.PROPERTY, property="#type")
class Execution {
...
}
objectMapper.registerSubtypes(
new NamedType(Execution.class, "Execution"), // the same name
....
);
objectMapper.readValue(....); // will be deserialized to an Execution instance

Categories