Skip to main content
Announcements
Introducing Qlik Answers: A plug-and-play, Generative AI powered RAG solution. READ ALL ABOUT IT!
cancel
Showing results for 
Search instead for 
Did you mean: 
orawajar
Contributor III
Contributor III

Why we can't get NB_LINE of tFileInputDelimited on flow?

Hi Master,
Why we can't get NB_LINE of tFileInputDelimited on flow? for example i have a simple job :
tFileInputDelimited ---Main ---- tJava_1
            |
On Component OK
            |
      tJava_2
tJava_1 :
System.out.println("On Flow : "+((Integer)globalMap.get("tFileInputDelimited_1_NB_LINE")));

tJava_2 :
System.out.println("On Component OK : "+((Integer)globalMap.get("tFileInputDelimited_1_NB_LINE")));

 when i run this job it give me :
On Flow : null
On Component OK : 11

Is there any way to get line number on Flow?
Thank you and best regards
Labels (3)
5 Replies
Anonymous
Not applicable

Hi,
Have you tried to use components TalendHelpCenter:tFlowMeterCatcher and TalendHelpCenter:tFlowMeter?

Best regards
Sabrina
Anonymous
Not applicable

Does anyone have an answer on this one? I've recently hit the issue too, and I see that no one has really explained this so far.

 

The most puzzling part is that if we do this as a subjob (OnComponentOk), it works fine, and the prior flow NB_LINE value is correct. If it is inline in the flow (from main), then the NB_LINE value is null.  Something is causing it to get set to null, because the GUI definitely shows that more than one row is being sent to the next component.

 

I did some poking in the code, and if I put a tJava inline and just print out the value of nb_line_tLogRow_1, it shows the correct count. If I try to access it via globalMap.get, then the value of tLogRow_1_NB_LINE is null. This can't possibly be correct...??

 

Can anyone explain this behavior?

 

Thanks,

Bruce

David_Beaty
Specialist
Specialist

Hi,

As the tFileInputDelimted component documentation says, the NB_LINES is an "after" value, so is not available during. However, there are 2 possible ways of doing this:


1/ In your tJavaRow component on the flow, add in a Numeric.Sequence and suggest you have it's Sequence Name as the filename you're reading in (this is probably the most robust solution).

2/ If you inspects the Java that gets created, where it assigns the global variable at the end, its something like : fid_tFileInputDelimited_1.getRowNumber() , you can also use this in the tJavaRow component on the flow, however I would strongly suggest option 1 rather than this.

 

Anonymous
Not applicable

Hi David --

 

Thanks for the reply; I'm glad to see this thread isn't completely dead (yet). 0683p000009MACn.png  I had to re-write my reply on this after your hints. I started out to say:

 

A couple of caveats:

 

First, this issue does not depend on tFileInputDelimited -- my problem exists regardless of the previous component. I came across the original thread because I was tracking down a similar end result as the OP, and this post seemed to be the closest to my problem. I wasn't focused on tFileInputDelimited specifically.

 

Second, I'm aware that the NB_LINE value is an after-value, and that's really part of the problem. I don't want to find out the value during the run, but it's NOT coming across as an actual integer after-value. It's coming out, after the component has completed, as a null value, despite there actually being rows transferred. In the GUI, I can see that 2 rows are passed along, and I have verified that in the actual generated code too. But when I evaluate that component's NB_LINE variable immediately after the component, it has a null value. Very frustrating.

 

(I'm leaving that in for some context, so if anyone else reads this, maybe they're thinking the same thing...)

 

I had to re-write this reply because, in coming up with a simple example to show my problem, I think I found my mistake in the job design. The flaw is in that the tJava and tJavaRow components run asynchronously while in the main flow. As such, they don't see the final value of NB_LINE until that subjob finishes. At that point, they do see the correct value. If connected via an OnComponentOk link, then they work as expected. Here's the job I created to illustrate my question:

 

(Generates 2 rows of random data, shows in a table, and then prints out the row transferred count.)

 

0683p000009M3yv.png

 

In the tJavaRow_1 (top row) and tJava_1 (second row) components, the value of NB_LINE (from their previous tLogRow components) is always null. When I put a tJava component after the subjob, like in tJava3 (top row), then the value is reported correctly. What caught my attention was that the debug output I added was coming out before the tLogRow components finished printing their table (the output was above the table). In the subjob approach, the debug output was after the table printed. Clearly, things were executing at different times than I expected. Here's the output of the run:

 

0683p000009M3yr.png

As you can see, tJavaRow_1 prints the value of NB_LINE twice (expected), but instead of 1, 2, stop, it gets null, null, stop. The data is transferred okay, but since the tJavaRow_1 starts running at the same time as the full subjob, that global variable still has a null value at that point. tJava didn't help me, since it was doing the same thing. Then I had to go back and research why the Java components acted that way. In the Talend docs, it very subtlety mentions that tJava is really intended for subjob execution (hence why it worked in tJava_3 in the top row). tJavaRow was my go-to component, since I wanted it to be in the main flow, but because of when it fires off, it wasn't coming up with the right value.

 

I then kind of hacked it, in that I used the approach in the third row above. In that one, I made the one subjob process the rows, and then in the tJavaRow_2 component, I stuffed my target (the last row of data received) into a context variable, and then referenced it in tJava_4 for processing. I didn't like that approach, since it seemed fairly kludgy, and it was only a valid use case because I only cared about the last row transferred; if I needed several rows, it wouldn't work (or I'd have to tBufferOutput) for a later component that needed to work on the set. Here's the output from the third row approach:

0683p000009M3z0.png

Like I said, it worked, but not really the best way to do it. tJavaFlex, though, got my problem solved.

 

tJavaFlex offers three separate execution contexts. One for start, main, and end. I don't care about start and main, in this case. But end is perfect. I want to execute my Java code AFTER the previous component completely finishes. tJavaFlex allows that. Here's the new job:

 

0683p000009M3wl.png

In this version, my code is in the end block, and results in this output:

0683p000009M3tc.png

Just what I expected. NB_LINE has the right value, and I'm able to get that last line in the flow and do some custom code work on it. Brilliant!

 

I think I skated by in my previous Talend jobs by using tJava and expecting that I knew how it was executing. The reality was that I should have been looking at how and when the three Java components would execute. Once I did that, it was clear that tJavaFlex was a better solution.

 

By the way, I had first done exactly what you recommended in your #2 option, and I agree that's not the best choice. But, it did work. Using that internal variable, I could see it as it iterated up, so I was able to get my end result. It wasn't pretty or good either, which is what initiated my original reply. I wanted a "right" solution.

 

I know you probably didn't intend to take me down this path, but it worked out, and I learned more about how to use these Java components. My thanks for pointing me in the right direction. I'm hoping my lengthy last reply will be helpful to others in understanding the issue here.

 

Thanks!

Bruce

David_Beaty
Specialist
Specialist

Hi Bruce,

 

That's some very inventive thought processes at work there, I'm glad you got to the solution you needed in this case, however I would add one further caveat.

 

Try not to wander into Java based solutions too much, as they will be at risk of being brittle when it comes to Talend upgrades, there's a component tMemorizeRows that might have achieved what you wanted completely as a Talend only solution.