Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
Hi There Talend community
Now I have an issue . I understand that rowstruct shouldn't be parsed as a parameter to a function within a routine and that instead the parameters should rather be the field of the rowstruct for example :
myClass.function(row1.name ,row1.surname)
Now my issue with this is that what happens when you dealing with a hundred different fields .this way of parsing fields to a function becomes tedious . now im able to parse a rowstruct as parameter by importing the rowstruct within the routine but when the i update my job's version number .the import will have to change each time .
my question :is there a way around the import issue? or is there a more convenient way of parsing the information as bulk to my routine without developing a wrapper class for the rowstruct?
I think I understand what you are doing here (I have used this technique for the same reasons), but I am not sure why changing the job's version number should affect this? As long as your row has not changed at all (name, columns, etc), then rowStruct you have copied over to your Routine should still be usable. Can you elaborate on what you are seeing?
unfortunately the import will look something like this:
import projectName.JobName_1_90.jobName.row5Struct;
its the version number within the job name thats giving me issues
Ah I see. I didn't consider that. I never use Talend version numbers. I would highly recommend NOT using them. You will find that once you create a new version, the old version is locked. It is far better to keep the version numbers static and use GIT or SVN to keep different versions.
However, given that you are using Talend versions, what you could do is this......but it is quite complicated.
First, find your RowStruct class inside your job's code. Mine (as an example) is below....
public static class row16Struct implements
routines.system.IPersistableRow<row16Struct> {
final static byte[] commonByteArrayLock_ALLPORT_DQ_Child = new byte[0];
static byte[] commonByteArray_ALLPORT_DQ_Child = new byte[0];
public String newColumn;
public String getNewColumn() {
return this.newColumn;
}
public Integer newColumn1;
public Integer getNewColumn1() {
return this.newColumn1;
}
private String readString(ObjectInputStream dis) throws IOException {
String strReturn = null;
int length = 0;
length = dis.readInt();
if (length == -1) {
strReturn = null;
} else {
if (length > commonByteArray_ALLPORT_DQ_Child.length) {
if (length < 1024
&& commonByteArray_ALLPORT_DQ_Child.length == 0) {
commonByteArray_ALLPORT_DQ_Child = new byte[1024];
} else {
commonByteArray_ALLPORT_DQ_Child = new byte[2 * length];
}
}
dis.readFully(commonByteArray_ALLPORT_DQ_Child, 0, length);
strReturn = new String(commonByteArray_ALLPORT_DQ_Child, 0,
length, utf8Charset);
}
return strReturn;
}
private void writeString(String str, ObjectOutputStream dos)
throws IOException {
if (str == null) {
dos.writeInt(-1);
} else {
byte[] byteArray = str.getBytes(utf8Charset);
dos.writeInt(byteArray.length);
dos.write(byteArray);
}
}
private Integer readInteger(ObjectInputStream dis) throws IOException {
Integer intReturn;
int length = 0;
length = dis.readByte();
if (length == -1) {
intReturn = null;
} else {
intReturn = dis.readInt();
}
return intReturn;
}
private void writeInteger(Integer intNum, ObjectOutputStream dos)
throws IOException {
if (intNum == null) {
dos.writeByte(-1);
} else {
dos.writeByte(0);
dos.writeInt(intNum);
}
}
public void readData(ObjectInputStream dis) {
synchronized (commonByteArrayLock_ALLPORT_DQ_Child) {
try {
int length = 0;
this.newColumn = readString(dis);
this.newColumn1 = readInteger(dis);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public void writeData(ObjectOutputStream dos) {
try {
// String
writeString(this.newColumn, dos);
// Integer
writeInteger(this.newColumn1, dos);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(super.toString());
sb.append("[");
sb.append("newColumn=" + newColumn);
sb.append(",newColumn1=" + String.valueOf(newColumn1));
sb.append("]");
return sb.toString();
}
public String toLogString() {
StringBuilder sb = new StringBuilder();
if (newColumn == null) {
sb.append("<null>");
} else {
sb.append(newColumn);
}
sb.append("|");
if (newColumn1 == null) {
sb.append("<null>");
} else {
sb.append(newColumn1);
}
sb.append("|");
return sb.toString();
}
/**
* Compare keys
*/
public int compareTo(row16Struct other) {
int returnValue = -1;
return returnValue;
}
private int checkNullsAndCompare(Object object1, Object object2) {
int returnValue = 0;
if (object1 instanceof Comparable && object2 instanceof Comparable) {
returnValue = ((Comparable) object1).compareTo(object2);
} else if (object1 != null && object2 != null) {
returnValue = compareStrings(object1.toString(),
object2.toString());
} else if (object1 == null && object2 != null) {
returnValue = 1;
} else if (object1 != null && object2 == null) {
returnValue = -1;
} else {
returnValue = 0;
}
return returnValue;
}
private int compareStrings(String string1, String string2) {
return string1.compareTo(string2);
}
}
Make a routine based on this code. You will have to handle your own imports, etc. Once you have your RowStruct routine, you can add useful methods. However, one you WILL need to add is a method to transfer your data. If you look at the above code, you will see a toString method. That format is constant. Therefore you can add a fromString method to your Routine to receive the String returned by toString and interpret that data in your Routine. So your code to pass your data between your Job's rowStruct and yours would be....
routines.MyRowStruct rs = new routines.MyRowStruct(); rs.readString(row16.toString());
At this point (assuming you have populated all columns), your new RowStruct will hold everything your Job's one does, but will remain able to be used across all versions.
Obviously this is a bit of a hack, but it will allow you to do what you want with a little bit of initial work. Alternatively, just don't use Talend versioning 🙂
Thank you for your solution and your advice regarding the job version, Now If its not a problem .I would like to ask why the compiler is moaning about the rowStruct import. it gives me an error regarding the import and then if close and open talend again there's no error . but then other times it will give me an error .Do you perhaps know of a solution to solve this . I hope you can understand what i mean .
I think I have seen this issue. I think it is an Eclipse issue. I've not found a bullet proof solution to this. What I generally do is ensure the job that is being referenced (ie the RowStruct within it) is open when I edit the routine.
Hi @rhall
Thank you for assistance but now unfortunately Talend isnt happy with the import or the parameter at all anymore. after committing the project to git and reImporting in Talend ,the job doesnt run and just throws exceptions in the routine and the tJavaRow
You will need to post the errors otherwise I have nothing to go on
above is the warning referring to the missing types and heres the stack trace :
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method createLists(row16Struct) from the type PrimaryValidations refers to the missing type row16Struct
And everything is the same as before the imports are there