I have a WSDL file in which one of the many operations simply returns a boolean instead of an object with fields:
<xs:element name="isUserActive" type="xs:boolean" />
To generate Java classes, I use CXF: org.apache.cxf.tools.wsdlto.WSDLToJava. The generated Port contains the following method signature:
#WebMethod(action = "isUserActive")
#WebResult(name = "isUserActiveResponse", targetNamespace = "http://company.com/1.0", partName = "parameters")
public boolean isUserActive(
#WebParam(partName = "parameters", name = "isUserActiveRequest", targetNamespace = "http://company.com/1.0") com.company.IsUserActiveRequest parameters
) throws Exception;
I also get an ObjectFactory for the boolean:
#XmlElementDecl(namespace = "http://company.com/1.0", name = "isUserActiveResponse")
public JAXBElement<Boolean> createIsUserActiveResponse(Boolean value) {
return new JAXBElement<Boolean>(_IsUserActiveResponse_QNAME, Boolean.class, null, value);
}
Unfortunately, Spring Boot doesn't understand that mapping and throws an exception when a client calls that endpoint: No adapter for endpoint [public boolean ... so I manually change the generated Port to return a JAXBElement<Boolean> instead of a boolean and use the ObjectFactory to create such an object in the implementation:
#PayloadRoot(namespace = TARGET_NAMESPACE, localPart = "isUserActiveRequest")
#ResponsePayload()
public JAXBElement<Boolean> isUserActive(#RequestPayload IsUserActiveRequest request) {
ObjectFactory factory = new ObjectFactory();
boolean result = doSomething();
return factory.createIsActiveResponse(result);
}
Obviously, whenever I re-generate the Java classes from the WSDL, those manual changes are discarded, so I'd like to know how I should configure WSDL2Java in order to generate the method signature as desired.
I've already tried to provide a binding-file setting generateElementProperty="true" but that would change the other generated classes as well by replacing their field's types to JAXBElement<T>. I'm just interested in that particular method overriding a primitive boolean as return type.
Related
I stored some information in a variable, but I do not know how to access it in my java code...
Example:
<sub-flow name="EnrichMessage" doc:name="EnrichMessage">
<component doc:name="Scenario01" class="Class01"/>
<set-variable variableName="Parameters" value="#[payload]" doc:name="Variable"/>
<flow-ref name="SubFlow01" doc:name="SubFlow01"/>
<component doc:name="Scenario02" class="Class02"/>
</sub-flow>
I already saw some incomplete answers, but still don't know how to do that. Anyone can post a complete answer?
Thanks.
In java there are a few ways to access variables depending the type of java class you are using:
onCall event class
public Object onCall(MuleEventContext eventContext, #Payload String payload)
throws Exception {
String returnPath = eventContext.getMessage().getProperty("myReturnPath", PropertyScope.OUTBOUND);
If the MuleMessage is passed:
public void process(#Payload MuleMessage payload ){
String returnPath = messge.getProperty("myReturnPath", PropertyScope.OUTBOUND);
Using an OutboundHeader annotation
public void process(#Payload String payload, #OutboundHeaders Map headers ){
String prop = headers.get("propname");
Add new Java Component to your flow and create new Java class implement Callable interface.
public Object onCall(MuleEventContext eventContext) throws Exception {
MuleMessage msg = eventContext.getMessage();
// you can access MuleMessage here
return msg;
}
Then, you can access your MuleMessage.
String method = msg.getProperty("http.method", PropertyScope.INBOUND);
If you want to add new property
msg.setProperty("foo", "bar", PropertyScope.INVOCATION);
Using Entity Framework I can create concrete classes from most of the sprocs in the database of a project I'm working on. However, some of the sprocs use dynamic SQL and as such no metadata is returned for the sproc.
So for a that sproc, I manually created a concrete class and now want to map the sproc output to this class and return a list of this type.
Using the following method I can get a collection of objects:
var results = connection.Query<object>("get_buddies",
new { RecsPerPage = 100,
RecCount = 0,
PageNumber = 0,
OrderBy = "LastestLogin",
ProfileID = profileID,
ASC = 1},
commandType: CommandType.StoredProcedure);
My concrete class contains
[DataContractAttribute(IsReference=true)]
[Serializable()]
public partial class LoggedInMember : ComplexObject
{
/// <summary>
/// No Metadata Documentation available.
/// </summary>
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
[DataMemberAttribute()]
public global::System.Int16 RowID
{
get
{
return _RowID;
}
set
{
OnRowIDChanging(value);
ReportPropertyChanging("RowID");
_RowID = StructuralObject.SetValidValue(value);
ReportPropertyChanged("RowID");
OnRowIDChanged();
}
}
private global::System.Int16 _RowID;
partial void OnRowIDChanging(global::System.Int16 value);
partial void OnRowIDChanged();
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
[DataMemberAttribute()]
public global::System.String NickName
{
get
{
return _NickName;
}
set
{
OnNickNameChanging(value);
ReportPropertyChanging("NickName");
_NickName = StructuralObject.SetValidValue(value, false);
ReportPropertyChanged("NickName");
OnNickNameChanged();
}
}
private global::System.String _NickName;
partial void OnNickNameChanging(global::System.String value);
partial void OnNickNameChanged();
.
.
.
Without having to iterate through the results and add the output parameters to the LoggedInMember object, how do I map these on the fly so I can return a list of them through a WCF service?
If I try var results = connection.Query<LoggedInMember>("sq_mobile_get_buddies_v35", ... I get the following error:
System.Data.DataException: Error parsing column 0 (RowID=1 - Int64)
---> System.InvalidCastException: Specified cast is not valid. at Deserialize...
At a guess your SQL column is a bigint (i.e. Int64 a.k.a. long) but your .Net type has a n Int16 property.
You could play around with the conversion and ignore the stored procedure by doing something like:
var results = connection.Query<LoggedInMember>("select cast(9 as smallint) [RowID] ...");
Where you are just selecting the properties and types you want to return your object. (smallint is the SQL equivalent of Int16)
The solution to this was to create a complex object derived from the sproc with EF:
public ProfileDetailsByID_Result GetAllProfileDetailsByID(int profileID)
{
using (IDbConnection connection = OpenConnection("PrimaryDBConnectionString"))
{
try
{
var profile = connection.Query<ProfileDetailsByID_Result>("sproc_profile_get_by_id",
new { profileid = profileID },
commandType: CommandType.StoredProcedure).FirstOrDefault();
return profile;
}
catch (Exception ex)
{
ErrorLogging.Instance.Fatal(ex); // use singleton for logging
return null;
}
}
}
In this case, ProfileDetailsByID_Result is the object that I manually created using Entity Framework through the Complex Type creation process (right-click on the model diagram, select Add/Complex Type..., or use the Complex Types tree on the RHS).
A WORD OF CAUTION
Because this object's properties are derived from the sproc, EF has no way of knowing if a property is nullable. For any nullable property types, you must manually configure these by selecting the property and setting its it's Nullable property to true.
I have a cxf JAX-RS service which looks something like the one below. When I submit a request with requested type "application/xml" I would expect that cxf automatically converts my return value into xml. This works for the method getData, but not for the other 2 methods. The other 2 methods return a simple String representation of the return value such as 2.0 or true. How do I get cxf to return a XML document for all 3 methods?
#WebService
#Consumes("application/xml")
#Produces("application/xml")
public interface MyServiceInterface {
final static String VERSION = "2.0";
#WebMethod
#GET
#Path("/version")
String getVersion();
#WebMethod
#GET
#Path("/data/{user}")
Data[] getData(#PathParam("user") String username) throws IOException;
#WebMethod
#GET
#Path("/user/{user}")
boolean doesUserExist(#PathParam("user") String username);
}
The issue is that neither String nor boolean has a natural representation as an XML document; XML requires an outer element, and neither CXF nor JAXB (the XML binding layer) knows what it should be.
The simplest method is to return the basic type inside a little JAXB-annotated wrapper:
#XmlRootElement
public class Version {
#XmlValue
public String version;
}
#XmlRootElement
public class UserExists {
#XmlValue
public boolean exists;
}
#WebService
#Consumes("application/xml")
#Produces("application/xml")
public interface MyServiceInterface {
final static String VERSION = "2.0";
#WebMethod
#GET
#Path("/version")
// TYPE CHANGED BELOW!
Version getVersion();
#WebMethod
#GET
#Path("/data/{user}")
Data[] getData(#PathParam("user") String username) throws IOException;
#WebMethod
#GET
#Path("/user/{user}")
// TYPE CHANGED BELOW!
UserExists doesUserExist(#PathParam("user") String username);
}
The other way of doing this would be to register providers that know how to convert strings and booleans into XML, but that's messy and affects your whole application in unexpected ways and you really shouldn't do that for simple types, OK?
I'm using Mono.Cecil to generate an assembly that contains a derived class that overrides a specific method in an imported base class. The override method is an 'implicit' override. The problem is that I cannot figure out how to designate it as an override.
I'm using the following code to create the override method.
void CreateMethodOverride(TypeDefinition targetType,
TypeDefinition baseClass, string methodName, MethodInfo methodInfo)
{
// locate the matching base class method, which may
// reside in a different module
MethodDefinition baseMethod = baseClass
.Methods.First(method => method.Name.Equals(methodName));
MethodDefinition newMethod = targetType.Copy(methodInfo);
newMethod.Name = baseMethod.Name;
newMethod.Attributes = baseMethod.Attributes;
newMethod.ImplAttributes = baseMethod.ImplAttributes;
newMethod.SemanticsAttributes = baseMethod.SemanticsAttributes;
targetType.Methods.Add(newMethod);
}
It is my understanding that an implicit override must have the same signature as the inherited method. Using the above code, when I view the resulting method in Reflector, the base class and the derived class methods have the exact same signature, namely "public virtual void f(int param)".
I've tried removing the explicit "virtual" attribute, but then the derived method ends up as "public void f(int param)'.
How do I get the derived method to have the correct "public override void f(int param)" signature?
NOTE: I have an extension method ("TypeDefinition.Copy") that clones a MethodInfo and returns a MethodDefinition by importing all of the referenced types, etc.
In your base class, let's say you generate the following method:
public virtual void f(int);
You have to make sure that it has the flag IsVirtual set to true. You also have to make sure that it has the flag IsNewSlot = true, to make sure that it has a new slot in the virtual method table.
Now, for the overridden methods, you want to generate:
public override void f(int);
To do so, you also need to have the method to be IsVirtual, but also to tell it that it's not a new virtual method, but that it implicitly overrides another, so you have to make it .IsReuseSlot = true.
And because you're using implicit overriding, you also have to make sure both methods are .IsHideBySig = true.
With that all set, you should have a proper overriding method.
For the benefit of other readers, here is the final result obtained by following JB's answer:
void CreateMethodOverride(TypeDefinition targetType,
TypeDefinition baseClass, string methodName, MethodInfo methodInfo)
{
MethodDefinition baseMethod = baseClass
.Methods.First(method => method.Name.Equals(methodName));
MethodDefinition newMethod = targetType.Copy(methodInfo);
newMethod.Name = baseMethod.Name;
// Remove the 'NewSlot' attribute
newMethod.Attributes = baseMethod.Attributes & ~MethodAttributes.NewSlot;
// Add the 'ReuseSlot' attribute
newMethod.Attributes |= MethodAttributes.ReuseSlot;
newMethod.ImplAttributes = baseMethod.ImplAttributes;
newMethod.SemanticsAttributes = baseMethod.SemanticsAttributes;
targetType.Methods.Add(newMethod);
}
I ran into a problem today when trying to set a field using FieldInfo.SetValue() passing a DynamicObject as the second argument. In my case, the field is a Guid and the DynamicObject should be able to convert itself to a one (using TryConvert) but it fails with an ArgumentException.
Some code that shows the problem:
// Simple impl of a DynamicObject to prove point
public class MyDynamicObj : DynamicObject
{
public override bool TryConvert(ConvertBinder binder, out object result)
{
result = null;
// Support converting this to a Guid
if (binder.Type == typeof(Guid))
{
result = Guid.NewGuid();
return true;
}
return false;
}
}
public class Test
{
public Guid MyField;
}
class Program
{
static void Main(string[] args)
{
dynamic myObj = new MyDynamicObj();
// This conversion works just fine
Guid guid = myObj;
var test = new Test();
var testField = typeof(Test).GetField("MyField");
// This, however, fails with:
// System.ArgumentException
// Object of type 'ConsoleApplication1.MyDynamicObj' cannot be converted to type 'System.Guid'.
testField.SetValue(test, myObj);
}
}
I'm not very familiar with the whole dynamicness of C# 4, but this felt to me like something that should work.. What am I doing wrong? Is there another way of doing this?
No, this shouldn't work - because the dynamic portion ends where your code ends. The compiler is calling a method with a signature of
void SetValue(Object obj, Object value)
That method call is dynamic, but it's just going to end up passing in a reference to the instance of MyDynamicObj. The call is resolved at execution time, but nothing in SetValue knows anything about the dynamic nature of the object whose reference you're passing in.
Basically you need to perform the dynamic part (the conversion in this case) in your code - the bit that involves the C# 4 compiler doing all its tricks. You've got to perform that conversion, and then you can call SetField.
To put it another way - it's a bit like calling SetField with a field of type XName, but passing in a string. Yes, there's a conversion from string to XName, but it's not SetField's job to work that out. That's the compiler's job.
Now, you can get this to work by making the compiler do some of the work, but you still need to do some with reflection:
static void Main(string[] args)
{
dynamic myObj = new MyDynamicObj();
var test = new Test();
var testField = typeof(Test).GetField("MyField");
var method = typeof(Program)
.GetMethod("Convert", BindingFlags.Static | BindingFlags.NonPublic);
method = method.MakeGenericMethod(testField.FieldType);
object converted = method.Invoke(null, new object[] {myObj});
testField.SetValue(test, converted);
}
static T Convert<T>(dynamic input)
{
return input;
}
You need an explicit cast to invoke the TryConvert:
testField.SetValue(test, (Guid)myObj);
Not sure if this is what you need though. Maybe there's some way to reflectively say ((DynamicObject)myObj).TryConvert(/*reflected destination type here*/, result)
Other attempts that failed, some of them require things like a certain interface be implemented, so they basically don't make use of TryConvert but maybe an alternative way to accomplish what you want:
Type secondType = testField.FieldType;
TypeConverter tc = TypeDescriptor.GetConverter(typeof(MyDynamicObj));
object secondObject = tc.ConvertTo(myObj,typeof( Guid));
//var secondObject = Convert.ChangeType(myObj, secondType);//Activator.CreateInstance(secondType);
//secondObject = myObj;
testField.SetValue(test, secondObject);