Returning Object from WCF Service - wcf

I am learning WCF. where I tried to return an object from my service to client after the operation completed from my client as required. But Its not giving any error and also not returning the result.
Service.svc.cs
public class myWCF : ImyWCF
{
public int myAddition(int IP_One, int IP_Two, out int IP_Three)
{
IP_Three = IP_One + IP_Two;
return IP_Three;
}
public MYTYPE mySubstraction()
{
MYTYPE mType = new MYTYPE();
mType.InpOne = 10;
mType.InpTwo = 20;
mType.InpThree = mType.InpTwo - mType.InpOne;
return mType;
}
}
Interface and Classes
[ServiceContract]
public interface ImyWCF
{
[OperationContract]
int myAddition(int IP_One, int IP_Two, out int IP_Three);
[OperationContract]
MYTYPE mySubstraction();
}
[DataContract]
public class myArithmatics
{
[DataMember]
public int IP_One;
[DataMember]
public int IP_Two;
[DataMember]
public int IP_Three;
}
[Serializable]
[DataContractAttribute(IsReference=true)]
public class MYTYPE
{
public int inpOne = 0;
public int inpTwo = 0;
public int inpThree = 0;
[DataMemberAttribute]
public int InpOne
{
get { return inpOne; }
set { inpOne = value; }
}
[DataMemberAttribute]
public int InpTwo
{
get { return inpTwo; }
set { inpTwo = value; }
}
[DataMemberAttribute]
public int InpThree
{
get { return inpThree; }
set { inpThree = value; }
}
}
Client App
Console.WriteLine("Service Started");
ClientMyWCF.ImyWCFClient oMYWcf = new ClientMyWCF.ImyWCFClient();
int INP_One = 10;
int INP_Two = 20;
int INP_Three = 0;
oMYWcf.myAddition(out INP_Three,INP_One,INP_Two);
Console.WriteLine("Out put from Service :"+ INP_Three.ToString());
ClientMyWCF.MYTYPE objMT = new ClientMyWCF.MYTYPE();
objMT.InpOne = 10;
objMT.InpTwo = 20;
//objMT.InpThree = 0;
oMYWcf.mySubstraction();
Console.WriteLine("Out put from Service :" + objMT.InpThree.ToString());
Console.ReadLine();
So any idea how to get the object returned?

I'm not sure why you're using an OUT parameter in the first call when you're returning the result of the operation as well as the OUT parameter.
Also, in the first method call (addition) you have the parameters in the wrong order.
In the second method call, you're not assigning the MYTYPE object to a variable.
I would suggest the following code:
public class myWCF : ImyWCF
{
// remove the OUT parameter
public int myAddition(int IP_One, int IP_Two)
{
return IP_One + IP_Two;
}
public MYTYPE mySubstraction()
{
MYTYPE mType = new MYTYPE();
mType.InpOne = 10;
mType.InpTwo = 20;
mType.InpThree = mType.InpTwo - mType.InpOne;
return mType;
}
}
Use the following in your program code:
Console.WriteLine("Service Started");
ClientMyWCF.ImyWCFClient oMYWcf = new ClientMyWCF.ImyWCFClient();
int INP_One = 10;
int INP_Two = 20;
int INP_Three = 0;
INP_Three = oMYWcf.myAddition(INP_One, INP_Two);
Console.WriteLine("Out put from Service :"+ INP_Three.ToString());
ClientMyWCF.MYTYPE objMT = new ClientMyWCF.MYTYPE();
// Not needed - these are set in the mySubtraction method
//objMT.InpOne = 10;
//objMT.InpTwo = 20;
//objMT.InpThree = 0;
objMT = oMYWcf.mySubstraction();
Console.WriteLine("Out put from Service :" + objMT.InpThree.ToString());
Console.ReadLine();

Remove the SerializableAttribute e.g; [Serializable] because there is no need to be serialize this object.
For class , use attribute [DataContract]
For class level properties , use attribute [DataMemberAttribute]
to expose the method , use attirbute [OperationContract]
these are standards for wcf service.

You can also remove these 2 attributes all together
[Serializable]
[DataContractAttribute(IsReference=true)]
By default, all public properties will be serialized. Also seeing your proxy would help. There are certain classes you should be inheriting from. I'm also not seeing a new instance of ServiceHost(typeof(MyService), myUri) being initialized which is strange. Maybe you have it encapsulated somewhere. Anyway, it's typical to construct a new channel using the ChannelFactory as such and to host a new service as such.

First of all, remove SerializableAttribute, using DataContractAttribute is enough.
Why you use out in myAddition method? it already returns the result through the return value, the third parameter is unnecessary.
In your code, you don't store the result from mySubstraction, while you read the objMT.InpThree that isn't assigned any value, I don't understand.

Related

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to java.util.List

I have a List<List<String>> dataTableList and I would like to get a specific list from there and put it on my List<String> dataList so that I could loop through that specific lists' value and alter it.
However, whenever I try to do that,I always get an error of:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to java.util.List.
Here's a sample of how I am trying to assign a specific list from dataTableList to dataList:
//First I looped through the List of Lists and called each list fetched as dataList
for(List<String> dataList : getTryLang().getDataTableList()){
//then, I created an iterator to be used later when I return the List I fetched with altered value
int iter = 0;
//next, I created a for-loop to iterate through the values of the List the I feched
for(int x; x < dataList.size(); x++){
//here, I formatted each value to amount or currency format.
dataList.set(x, getDataConvert().convertAmount(dataList.get(x)));
//finally, after I formatted everything, I returned it or set it to the specific index it's been located before
getTryLang().getDataTableList().set(iter, dataList);
}
iter++;
}
EDIT:
Here's my code and I modified some of it and didn't include some so that I could focus on expressing where the problem occurs.
Here's my TryLang.java:
#ManagedBean
#SessionScoped
public class TryLang implements Serializable {
public TryLang() {}
//declare
private List<List<String>> dataTableList;
//getter setter
public List<List<String>> getDataTableList() {
return dataTableList == null ? dataTableList = new ArrayList<>() : dataTableList;
}
public void setDataTableList(List<List<String>> dataTableList) {
this.dataTableList = dataTableList;
}
}
Then here's my BookOfAccountsController.java:
#ManagedBean
#RequestScoped
public class BooksOfAccountsController implements Serializable {
public BooksOfAccountsController() {}
//declare
#ManagedProperty(value = "#{dataConvert}")
private DataConvert dataConvert;
#ManagedProperty(value = "#{tryLang}")
private TryLang tryLang;
//getter setter NOTE: I wouldn't include other getter setters to shorten the code here :)
public TryLang getTryLang() {
return tryLang == null ? tryLang = new TryLang() : tryLang;
}
public void setTryLang(TryLang tryLang) {
this.tryLang = tryLang;
}
//I would just go straight to the method instead
public void runBooksOfAccounts() throws SystemException, SQLException {
//So there are dbCons here to connect on my DB and all. And I'll just go straight on where the List<List<String>> is being set
//Here's where the List<List<String>> is being set
getTryLang().setDataTableList(getCemf().getFdemf().createEntityManager().createNativeQuery("SELECT crj.* FROM crj_rep crj").getResultList());
getTryLang().setDataTableColumns(getCemf().getFdemf().createEntityManager().createNativeQuery("SELECT col.column_name FROM information_schema.columns col WHERE table_schema = 'public' AND table_name = 'crj_rep'").getResultList());
for (int x = 0; x < getTryLang().getDataTableColumns().size(); x++) {
try {
Integer.parseInt(getTryLang().getDataTableColumns().get(x));
getTryLang().getDataTableColumns().set(x, getDataConvert().accountCodeConvert(getTryLang().getDataTableColumns().get(x)));
//then here is where the error points at
for (List<String> dataList : getTryLang().getDataTableList()) {
try{
int iter = 0;
dataList.set(x, getDataConvert().convertAmount(new BigDecimal(dataList.get(x))));
getTryLang().getDataTableList().set(iter, dataList);
iter++;
}catch(ClassCastException ne){
System.out.println("cannot convert " + ne);
}
}
} catch (NumberFormatException ne) {
//print the error
}
}
}
}

Entity not posting to restful service

I'm having trouble posting a request to a restfull service.
It looks like my Entity is not getting converted into json correctly.
I get a 400 Bad request response.
I suspect it's the List of DateTimeRange objects causing the issue - as I have a very similar request that works but all the pojos properties are Strings.
Do I need to annotate my Entity to enable marshalling to/from json for Lists and my custom DateTimeRange?
String actionUrl = buildUrl( myResftullUrlTest );
Client client = ClientBuilder.newClient().register( JacksonJsonProvider.class );
Builder target = client.target( actionUrl ).request();
CreateWebinarRequest createWebinarRequest = new CreateWebinarRequest();
createWebinarRequest.setDescription("Test1 desc");
createWebinarRequest.setSubject("Test1 subject")
createWebinarRequest.setTimeZone("Europe/Dublin")
List<DateTimeRange> dateTimeRangeParam = new ArrayList<DateTimeRange>();
DateTimeRange dateTimeRange = new DateTimeRange();
dateTimeRange.setStartTime( "2016-11-03T08:34:12" );
dateTimeRange.setEndTime( "2016-11-03T09:34:12" );
dateTimeRangeParam.add( dateTimeRange );
createWebinarRequest.setTimes( dateTimeRangeParam );
Response response = null;
switch ( goToTrainingRequestData.getRequestType() ) {
case HTTP_POST :
response = target.buildPost( Entity.json(createWebinarRequest) ).invoke();
...
}
}
CreateWebinarRequest:
public class CreateWebinarRequest implements Serializable {
private String subject = null;
private String description = null;
private List<DateTimeRange> times = new ArrayList<DateTimeRange>();
private String timeZone = null;
public String getSubject() {
return subject;
}
public void setSubject( String subject ) {
this.subject = subject;
}
public String getDescription() {
return description;
}
public void setDescription( String description ) {
this.description = description;
}
public List<DateTimeRange> getTimes() {
return times;
}
public void setTimes( List<DateTimeRange> times ) {
this.times = times;
}
public String getTimeZone() {
return timeZone;
}
public void setTimeZone( String timeZone ) {
this.timeZone = timeZone;
}
}
DateTimeRange:
public class DateTimeRange {
private String startTime = null;
private String endTime = null;
public String getStartTime() {
return startTime;
}
public void setStartTime( String startTime ) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime( String endTime ) {
this.endTime = endTime;
}
}
Problem solved guys and gals!
Nothing wrong with any data marshalling, I got the detailed response from server with:
String error = response.readEntity( String.class );
And it was a boo boo on my behalf!
{"errorCode":"RequestValidationError","description":"Request contains invalid parameters. See validationErrorCodes for specific errors.","Details":"times cannot be in past","incident":"6100682426566883853","validationErrorCodes":[{"code":"requestStartTimeInPast","description":"times cannot be in past"}]}

JNA - output parameter in DLL

How can I get the output parameter, which is in a method in a C++ DLL?
public class MyClass {
public int error = 0;
public String MyMethod(){
String str = null;
error = error(str);
if (error == 0){
return str;
}
else
return null;
}
public native int error(String outputparam);
static {
Native.register("MyDLL");
}
}
See this JNA FAQ entry, which explains how to extract a "returned" string from a buffer used as a parameter.

Data member default values, how to figure out whether something was really sent?

By default, WCF deserializes missing elements into default values like null, 0 or false. The problem with this approach is that if it's a basic type like number 0 I'm not sure whether it means the real value sent by an external system or a default value generated by WCF.
So my question is: Is it possible to find out at run-time whether the default value means "I didn't send anything".
This is crucial because we can't update and overwrite existing data in the database with the default values just because the external system didn't send a particular element this time (data corruption).
Microsoft's short answer is "It is up to the receiving endpoint to appropriately interpret a missing element."
Data member default values
http://msdn.microsoft.com/en-us/library/aa347792.aspx
Can somebody please clarify what's that supposed to mean?
Thanks
If you define your data members as properties, you can use whether the setter was called or not to decide whether some value was sent. The code below shows one data contract which knows whether it deserialized its fields.
public class Post_51ca1ead_2f0a_4912_a451_374daab0101b
{
[DataContract(Name = "Person", Namespace = "")]
public class Person
{
string name;
int age;
bool nameWasSent;
bool ageWasSent;
[DataMember]
public string Name
{
get
{
return this.name;
}
set
{
this.nameWasSent = true;
this.name = value;
}
}
[DataMember]
public int Age
{
get
{
return this.age;
}
set
{
this.ageWasSent = true;
this.age = value;
}
}
[OnDeserializing]
void OnDeserializing(StreamingContext ctx)
{
this.ageWasSent = false;
this.nameWasSent = false;
}
public override string ToString()
{
return string.Format("Person[Name={0},Age={1}]",
nameWasSent ? name : "UNSPECIFIED",
ageWasSent ? age.ToString() : "UNSPECIFIED");
}
}
public static void Test()
{
MemoryStream ms = new MemoryStream();
DataContractSerializer dcs = new DataContractSerializer(typeof(Person));
dcs.WriteObject(ms, new Person { Name = "John", Age = 30 });
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
string noAge = "<Person><Name>John</Name></Person>";
ms = new MemoryStream(Encoding.UTF8.GetBytes(noAge));
object p = dcs.ReadObject(ms);
Console.WriteLine("No age: {0}", p);
string noName = "<Person><Age>45</Age></Person>";
ms = new MemoryStream(Encoding.UTF8.GetBytes(noName));
p = dcs.ReadObject(ms);
Console.WriteLine("No name: {0}", p);
}
}

How to rename a component column that is a foreign key?

We are using fluentnhibernate with automapping and we have a naming convention that all columns that are foreign keys, there column name will end with "Key". So we have a convention that looks like this:
public class ForeignKeyColumnNameConvention : IReferenceConvention
{
public void Apply ( IManyToOneInstance instance )
{
// name the key field
string propertyName = instance.Property.Name;
instance.Column ( propertyName + "Key" );
}
}
This works great until we created a component in which one of its values is a foreign key. By renaming the column here it overrides the default name given to the component column which includes the ComponentPrefix which is defined in the AutomappingConfiguration. Is there a way for me to get the ComponentPrefix in this convention? or is there some other way for me to get the column name for components with a property that is a foreign key to end in the word "Key"?
After a lot of fiddling and trial & error (thus being tempted to use your solution with Reflection) I came up with the following:
This method depends on the order of the execution of the conventions. This convention-order happens via a strict hierarchy. In this example, at first, the convention of the component (IDynamicComponentConvention) is being handled and after that the conventions of the inner properties are being handled such as the References mapping (IReferenceConvention).
The strict order is where we make our strike:
We assemble the correct name of the column in the call to Apply(IDynamicComponentConvention instance), put it on the queue. Note that a Queue<T> is used which is a FIFO (first-in-first-out) collection type thus it keeps the order correctly.
Almost immediately after that, Apply(IManyToOneInstanceinstance) is called. We check if there is anything in the queue. If there is, we take it out of the queue and set it as column name. Note that you should not use Peek() instead of Dequeue() as it does not remove the object from the queue.
The code is as follows:
public sealed class CustomNamingConvention : IDynamicComponentConvention, IReferenceConvention {
private static Queue<string> ColumnNames = new Queue<string>();
public void Apply(IDynamicComponentInstance instance) {
foreach (var referenceInspector in instance.References) {
// All the information we need is right here
// But only to inspect, no editing yet :(
// Don't worry, just assemble the name and enqueue it
var name = string.Format("{0}_{1}",
instance.Name,
referenceInspector.Columns.Single().Name);
ColumnNames.Enqueue(name);
}
}
public void Apply(IManyToOneInstance instance) {
if (!ColumnNames.Any())
// Nothing in the queue? Just return then (^_^)
return;
// Set the retrieved string as the column name
var columnName = ColumnNames.Dequeue();
instance.Column(columnName);
// Pick a beer and celebrate the correct naming!
}
}
I Have figured out a way to do this using reflection to get to the underlying mapping of the IManyToOneInspector exposed by the IComponentInstance but was hoping there was a better way to do this?
Here is some example code of how I achieved this:
#region IConvention<IComponentInspector, IComponentInstance> Members
public void Apply(IComponentInstance instance)
{
foreach (var manyToOneInspector in instance.References)
{
var referenceName = string.Format("{0}_{1}_{2}{3}", instance.EntityType.Name, manyToOneInspector.Property.PropertyType.Name, _autoMappingConfiguration.GetComponentColumnPrefix(instance.Property), manyToOneInspector.Property.Name);
if(manyToOneInspector.Property.PropertyType.IsSubclassOf(typeof(LookupBase)))
{
referenceName += "Lkp";
}
manyToOneInspector.Index ( string.Format ( "{0}_FK_IDX", referenceName ) );
}
}
#endregion
public static class ManyToOneInspectorExtensions
{
public static ManyToOneMapping GetMapping(this IManyToOneInspector manyToOneInspector)
{
var fieldInfo = manyToOneInspector.GetType ().GetField( "mapping", BindingFlags.NonPublic | BindingFlags.Instance );
if (fieldInfo != null)
{
var manyToOneMapping = fieldInfo.GetValue( manyToOneInspector ) as ManyToOneMapping;
return manyToOneMapping;
}
return null;
}
public static void Index(this IManyToOneInspector manyToOneInspector, string indexName)
{
var mapping = manyToOneInspector.GetMapping ();
mapping.Index ( indexName );
}
public static void Column(this IManyToOneInspector manyToOneInspector, string columnName)
{
var mapping = manyToOneInspector.GetMapping ();
mapping.Column ( columnName );
}
public static void ForeignKey(this IManyToOneInspector manyToOneInspector, string foreignKeyName)
{
var mapping = manyToOneInspector.GetMapping();
mapping.ForeignKey ( foreignKeyName );
}
}
public static class ManyToOneMappingExtensions
{
public static void Index (this ManyToOneMapping manyToOneMapping, string indexName)
{
if (manyToOneMapping.Columns.First().IsSpecified("Index"))
return;
foreach (var column in manyToOneMapping.Columns)
{
column.Index = indexName;
}
}
public static void Column(this ManyToOneMapping manyToOneMapping, string columnName)
{
if (manyToOneMapping.Columns.UserDefined.Count() > 0)
return;
var originalColumn = manyToOneMapping.Columns.FirstOrDefault();
var column = originalColumn == null ? new ColumnMapping() : originalColumn.Clone();
column.Name = columnName;
manyToOneMapping.ClearColumns();
manyToOneMapping.AddColumn(column);
}
public static void ForeignKey(this ManyToOneMapping manyToOneMapping, string foreignKeyName)
{
if (!manyToOneMapping.IsSpecified("ForeignKey"))
manyToOneMapping.ForeignKey = foreignKeyName;
}
}