Your Parser class has a package statement at the top: package ua_parser;
You will need to specify the fully-qualified package+class name in the EXTERNAL NAME clause of the CREATE FUNCTION command. Try this:
CREATE FUNCTION ua_family (agentString CHAR(30))
RETURNS CHAR(30)
LANGUAGE JAVA
NO SQL
PARAMETER STYLE JAVA
CALLED ON NULL INPUT
EXTERNAL NAME 'UA_Jar:ua_parser.Parser.parseUserAgent(java.lang.String) returns java.lang.String';
I am getting the same error when migrating an existing java UDF on TD version 14 to TD version 15. Has anything changed in they way EXTERNAL NAME parameter of replace function is specified? Here is what I am using, I have replaced variable names with generic names below. I did a show function on the version 14 database where this is already installed and tried to run it on the version 15.
REPLACE FUNCTION "SYSLIB"."UDFName" ( "var1" VARCHAR(100), "var2" VARCHAR(2000), "var3" VARCHAR(2000), "var4" VARCHAR(250), "var5" VARCHAR(5000)) RETURNS VARCHAR(200) CHARACTER SET LATIN SPECIFIC "specFunName" LANGUAGE JAVA NO SQL NO EXTERNAL DATA PARAMETER STYLE JAVA DETERMINISTIC RETURNS NULL ON NULL INPUT EXTERNAL NAME 'JarId:package.classname.functionname(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String)returns java.lang.String';
The Error is
Failed [7980 : HY000] A JAVA method in the specified Jar which matches that in the EXTERNAL NAME clause was not found.
Where exactly are the jar files stored on the nodes? as last option I am thinking of trying with downloading the jar file from the TD version 14 database and using it instead of using the jar file on local client.
Thanks in advance.
Hi,
We have the next SQL file:
------------------------------------------------------ ------------------------------------------------------ --------------
CALL SQLJ.REMOVE_JAR('UA_Jar',0);
CALL SQLJ.INSTALL_JAR('CJ!/home/tdatuser/java/Parser.zip',' UA_Jar',0);
CREATE FUNCTION ua_family (agentString CHAR(30))
RETURNS CHAR(30)
LANGUAGE JAVA
NO SQL
PARAMETER STYLE JAVA
CALLED ON NULL INPUT
EXTERNAL NAME 'UA_Jar:Parser.parseUserAgent(java.lang.String) returns java.lang.String';
------------------------------------------------------ ------------------------------------------------------ --------------
We got the following error (can not found the 'Parser' class) when we run it through bteq:
+---------+---------+---------+---------+---------+--- ------+---------+----
CALL SQLJ.REMOVE_JAR('UA_Jar',0);
*** Procedure has been executed.
*** Total elapsed time was 1 second.
+---------+---------+---------+---------+---------+--- ------+---------+----
CALL SQLJ.INSTALL_JAR('CJ!/home/tdatuser/java/Parser.zip',' UA_Jar',0);
*** Procedure has been executed.
*** Warning: 9241 Check output for possible warnings encountered in Installing or Replacing a JAR.
*** Total elapsed time was 1 second.
Check output for possible warnings.
------------------------------------------------------ ---------------------
0 Wed Sep 24 08:13:56 EDT 2014 ua_parser/
2095 Wed Sep 24 07:00:52 EDT 2014 ua_parser/CachingParser.class
1209 Wed Sep 24 07:00:52 EDT 2014 ua_parser/Client.class
1333 Wed Sep 24 07:00:52 EDT 2014 ua_parser/Device.class
2081 Wed Sep 24 07:00:52 EDT 2014 ua_parser/DeviceParser.class
1183 Wed Sep 24 07:00:52 EDT 2014 ua_parser/DeviceParser$DevicePattern.class
2304 Wed Sep 24 07:00:52 EDT 2014 ua_parser/OS.class
2177 Wed Sep 24 07:00:52 EDT 2014 ua_parser/OSParser.class
1761 Wed Sep 24 07:00:52 EDT 2014 ua_parser/OSParser$OSPattern.class
2427 Wed Sep 24 07:00:52 EDT 2014 ua_parser/Parser.class
2070 Wed Sep 24 07:00:52 EDT 2014 ua_parser/UserAgent.class
2241 Wed Sep 24 07:00:52 EDT 2014 ua_parser/UserAgentParser.class
1651 Wed Sep 24 07:00:52 EDT 2014 ua_parser/UserAgentParser$UAPattern.class
45317 Wed Sep 24 06:29:00 EDT 2014 ua_parser/regexes.yaml
+---------+---------+---------+---------+---------+--- ------+---------+----
CREATE FUNCTION ua_family (agentString CHAR(30))
RETURNS CHAR(30)
LANGUAGE JAVA
NO SQL
PARAMETER STYLE JAVA
CALLED ON NULL INPUT
EXTERNAL NAME 'UA_Jar:Parser.parseUserAgent(java.lang.String) returns java.lang.String';
*** Create function completed with error(s).
*** Warning: 7980 A JAVA method in the specified Jar which matches that in the EXTERNAL NAME clause was not found.
*** Total elapsed time was 2 seconds.
Errors/Warnings reported while creating a Java XSP/UDF
------------------------------------------------------ ---------------------
08:33:54,895 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
08:33:54,895 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
08:33:54,896 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [jar:file:/opt/teradata/tdat/tdbms/15.00.00.07/bin/ javFnc.jar!/logback.xml]
08:33:54,946 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationActio n - debug attribute not set
08:33:54,952 |-ERROR in ch.qos.logback.core.util.ContextUtil@7f5663a2 - Failed to get local hostname java.net.UnknownHostException: TDExpress15008_Sles10: TDExpress15008_Sles10
at java.net.UnknownHostException: TDExpress15008_Sles10: TDExpress15008_Sles10
at at java.net.InetAddress.getLocalHost(InetAddress.java: 1374)
at at ch.qos.logback.core.util.ContextUtil.getLocalHostName( ContextUtil.java:30)
at at ch.qos.logback.core.util.ContextUtil.addHostNameAsProp erty(ContextUtil.java:39)
at at ch.qos.logback.classic.joran.action.ConfigurationActio n.begin(ConfigurationAction.java:47)
at at ch.qos.logback.core.joran.spi.Interpreter.callBeginAct ion(Interpreter.java:273)
at at ch.qos.logback.core.joran.spi.Interpreter.startElement (Interpreter.java:145)
at at ch.qos.logback.core.joran.spi.Interpreter.startElement (Interpreter.java:127)
at at ch.qos.logback.core.joran.spi.EventPlayer.play(EventPl ayer.java:40)
at at ch.qos.logback.core.joran.spi.Interpreter.play(Interpr eter.java:332)
at at ch.qos.logback.core.joran.GenericConfigurator.doConfig ure(GenericConfigurator.java:126)
at at ch.qos.logback.core.joran.GenericConfigurator.doConfig ure(GenericConfigurator.java:93)
at at ch.qos.logback.core.joran.GenericConfigurator.doConfig ure(GenericConfigurator.java:52)
at at ch.qos.logback.classic.util.ContextInitializer.configu reByResource(ContextInitializer.java:77)
at at ch.qos.logback.classic.util.ContextInitializer.autoCon fig(ContextInitializer.java:150)
at at org.slf4j.impl.StaticLoggerBinder.init(StaticLoggerBin der.java:85)
at at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLogge rBinder.java:55)
at at org.slf4j.LoggerFactory.bind(LoggerFactory.java:121)
at at org.slf4j.LoggerFactory.performInitialization(LoggerFa ctory.java:111)
at at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactor y.java:268)
at at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java: 241)
at at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java: 254)
at at com.teradata.fnc.JarManager.<clinit>(JarManager.java: 61)
at at com.teradata.fnc.JavaPtest.<clinit>(JavaPtest.java: 269)
08:33:54,952 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
08:33:54,955 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [stdout]
08:33:54,985 |-INFO in ch.qos.logback.classic.joran.action.LevelAction - ROOT level set to OFF
08:33:54,985 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [stdout] to Logger[ROOT]
java.lang.ClassNotFoundException: Parser
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java: 190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at com.teradata.fnc.JarURLLoader.locateClass(JarURLLoader .java:138)
at com.teradata.fnc.JarManager.checkClass(JarManager.java :291)
at com.teradata.fnc.JarManager.checkMethod(JarManager.jav a:227)
at com.teradata.fnc.JavaPtest.main(JavaPtest.java:373)
+---------+---------+---------+---------+---------+--- ------+---------+----
*** Warning: EOF on INPUT stream.
*** BTEQ exiting due to EOF on stdin.
*** Exiting BTEQ...
*** RC (return code) = 0
We compiled with (on Linux TD node):
javac -target 1.6 -classpath /home/tdatuser/java/commons-collections-3.2.1.jar:/ home/tdatuser/java/snakeyaml-1.10.jar:/home/tdatuser/ java/javFnc.jar CachingParser.java Client.java Device.java DeviceParser.java OS.java OSParser.java Parser.java UserAgent.java UserAgentParser.java
We have several files, but the ua_parser/Parser.class file comes from the Parser.java file (and it just contains the public class Parser) :
------------------------------------------------------ ------------------------------------------------------ --------------
package ua_parser;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
/**
* Java implementation of <a href="https://github.com/tobie/ua-parser">UA Parser</a>
*
* @author Steve Jiang (@sjiang) <gh at iamsteve com>
*/
public class Parser {
private static final String REGEX_YAML_PATH = "/ua_parser/regexes.yaml";
private UserAgentParser uaParser;
private OSParser osParser;
private DeviceParser deviceParser;
public Parser() throws IOException {
this(Parser.class.getResourceAsStream(REGEX_YAML_PATH) );
}
public Parser(InputStream regexYaml) {
initialize(regexYaml);
}
public Client parse(String agentString) {
UserAgent ua = parseUserAgent(agentString);
OS os = parseOS(agentString);
Device device = deviceParser.parse(agentString);
return new Client(ua, os, device);
}
public UserAgent parseUserAgent(String agentString) {
return uaParser.parse(agentString);
}
public Device parseDevice(String agentString) {
return deviceParser.parse(agentString);
}
public OS parseOS(String agentString) {
return osParser.parse(agentString);
}
private void initialize(InputStream regexYaml) {
Yaml yaml = new Yaml(new SafeConstructor());
@SuppressWarnings("unchecked")
Map<String,List<Map<String,String>>> regexConfig = (Map<String,List<Map<String,String>>>) yaml.load(regexYaml);
List<Map<String,String>> uaParserConfigs = regexConfig.get("user_agent_parsers");
if (uaParserConfigs == null) {
throw new IllegalArgumentException("user_agent_parsers is missing from yaml");
}
uaParser = UserAgentParser.fromList(uaParserConfigs);
List<Map<String,String>> osParserConfigs = regexConfig.get("os_parsers");
if (osParserConfigs == null) {
throw new IllegalArgumentException("os_parsers is missing from yaml");
}
osParser = OSParser.fromList(osParserConfigs);
List<Map<String,String>> deviceParserConfigs = regexConfig.get("device_parsers");
if (deviceParserConfigs == null) {
throw new IllegalArgumentException("device_parsers is missing from yaml");
}
deviceParser = DeviceParser.fromList(deviceParserConfigs);
}
}
------------------------------------------------------ ------------------------------------------------------ --------------
Who can help here ? We are looking for a Java UDF expert ..