I've created a custom Talend component, which at certain step connects to an external Http service. For that, I'm using org.apache.commons.httpclient
through javajet imports. I've seen the modules already exist in the Modules view. Nevertheless, when running a job the console outputs:
Execution failed : Failed to generate code.
[----------
1. ERROR in /Users/frb/Downloads/TOS_DI-20160510_1709-V6.2.0/workspace/.JETEmitters/src/org/talend/designer/codegen/translators/ngsi/orion/TOrionAppendBeginJava.java (at line 14)
import org.apache.commons.httpclient.*;
^^^^^^^^^^
The import org.apache cannot be resolved
----------
2. ERROR in /Users/frb/Downloads/TOS_DI-20160510_1709-V6.2.0/workspace/.JETEmitters/src/org/talend/designer/codegen/translators/ngsi/orion/TOrionAppendBeginJava.java (at line 15)
import org.apache.commons.httpclient.methods.*;
^^^^^^^^^^
The import org.apache cannot be resolved
----------
3. ERROR in /Users/frb/Downloads/TOS_DI-20160510_1709-V6.2.0/workspace/.JETEmitters/src/org/talend/designer/codegen/translators/ngsi/orion/TOrionAppendBeginJava.java (at line 16)
import org.apache.commons.httpclient.params.HttpMethodParams;;
^^^^^^^^^^
The import org.apache cannot be resolved
----------
3 problems (3 errors)
]
Any hints about how to fix this issue? My Talend version is 6.2.0.
EDIT 1
This is my begin code:
<%@ jet
imports="
org.talend.core.model.process.INode
org.talend.core.model.process.ElementParameterParser
org.talend.core.model.metadata.IMetadataTable
org.talend.core.model.metadata.IMetadataColumn
org.talend.core.model.process.IConnection
org.talend.core.model.process.IConnectionCategory
org.talend.designer.codegen.config.CodeGeneratorArgument
org.talend.core.model.metadata.types.JavaTypesManager
org.talend.core.model.metadata.types.JavaType
java.util.List
java.util.Map
org.apache.commons.httpclient.*
org.apache.commons.httpclient.methods.*
org.apache.commons.httpclient.params.HttpMethodParams
"
%>
<%
// Get the CID
CodeGeneratorArgument codeGenArgument = (CodeGeneratorArgument) argument;
INode node = (INode)codeGenArgument.getArgument();
String cid = node.getUniqueName();
// Get the component parameters
String orionEndpoint = ElementParameterParser.getValue(node, "__ORION_ENDPOINT__");
String authEndpoint = ElementParameterParser.getValue(node, "__AUTH_ENDPOINT__");
String authUsername = ElementParameterParser.getValue(node, "__AUTH_USERNAME__");
String authPassword = ElementParameterParser.getValue(node, "__AUTH_PASSWORD__");
String entityIdField = ElementParameterParser.getValue(node, "__ENTITY_ID_FIELD__");
String entityTypeField = ElementParameterParser.getValue(node, "__ENTITY_TYPE_FIELD__");
String defaultEntityType = ElementParameterParser.getValue(node, "__DEFAULT_ENTITY_TYPE__");
String ignoredFilds = ElementParameterParser.getValue(node, "__IGNORED_FIELDS__");
%>
System.out.println("I am the begin section");
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(<%=authEndpoint%>);
method.setRequestHeader(new Header("Content-Type", "application/json"));
method.setRequestBody("{\"username\":\"" + <%=authUsername%> + "\",\"password\":\"" + <%=authPassword%> + "\"}");
try {
int statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
System.err.println("Method failed: " + method.getStatusLine());
} // if
byte[] responseBody = method.getResponseBody();
System.out.println(new String(responseBody));
} catch (HttpException e) {
System.err.println("Fatal protocol violation: " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
System.err.println("Fatal transport error: " + e.getMessage());
e.printStackTrace();
} finally {
method.releaseConnection();
} // try
EDIT 2
I've added the following to my Component Descriptor file:
<IMPORTS>
<IMPORT
NAME="commons-httpclient"
MODULE="commons-httpclient-3.1.jar"
REQUIRED="true"
/>
</IMPORTS>
Now, in the modules view I'm able to see the following:
Sadly, the component outputs the same errors.
EDIT 3
After removing the imports and using fully qualified names, as suggested by @Balazs Gunics, the code seems to be generated. Nevertheless, some other errors related to commons-httpclient arise at running time:
Starting job job_tOrionAppend at 08:20 21/06/2016.
[statistics] connecting to socket on port 3916
[statistics] connected
I am the begin section
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
at org.apache.commons.httpclient.HttpClient.<clinit>(HttpClient.java:66)
at iotp_talend_connectors.job_torionappend_0_1.job_tOrionAppend.tMysqlInput_1Process(job_tOrionAppend.java:854)
at iotp_talend_connectors.job_torionappend_0_1.job_tOrionAppend.tMysqlConnection_1Process(job_tOrionAppend.java:422)
at iotp_talend_connectors.job_torionappend_0_1.job_tOrionAppend.runJobInTOS(job_tOrionAppend.java:1355)
at iotp_talend_connectors.job_torionappend_0_1.job_tOrionAppend.main(job_tOrionAppend.java:1212)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
[statistics] disconnected
[statistics] disconnected
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 5 more
Job job_tOrionAppend ended at 08:20 21/06/2016. [exit code=1]
So in the begin.javajet code of yours the following code will only import these libraries for the code generation itself. But you need them to the generated code. Generating java using java makes it hard to oversee this.
<%@ jet
imports="
org.apache.commons.httpclient.*
org.apache.commons.httpclient.methods.*
org.apache.commons.httpclient.params.HttpMethodParams
So what you need is to have these imports added to the generated code. Well that is not really possible :( https://www.talendforge.org/forum/viewtopic.php?id=3670 To do that you need to modify the xml descriptor for your component. So your imports are right. All you have to do is make sure you use the fully qualified names. I.e.: This piece of code:
System.out.println("I am the begin section");
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(<%=authEndpoint%>);
Have to be rewritten to look like this:
System.out.println("I am the begin section");
org.apache.commons.httpclient.HttpClient client =
new org.apache.commons.httpclient.HttpClient();
org.apache.commons.httpclient.methods.PostMethod method =
new org.apache.commons.httpclient.methods.PostMethod(<%=authEndpoint%>);
Yes, it would be way more elegant if we could import the classes and use them.