SNMP не работает в хранимой процедуре Java
Я пытаюсь выполнить процедуру Java в Oracle JVM. Эта процедура отправляет на принтер запрос SNMP, чтобы узнать его имя; он использует библиотеку SNMP4j
import java.io.IOException;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
public class Get_ink_levels_devices {
Snmp snmp = null;
String address = null;
/**
* Constructor
* @param add
*/
public Get_ink_levels_devices(String add)
{
address = add;
}
public static void main(String[] args) throws IOException {
/**
* Port 161 is used for Read and Other operations
* Port 162 is used for the trap generation
*/
Get_ink_levels_devices client = new Get_ink_levels_devices("udp:192.168.115.77/161");
client.start();
/**
* OID - .1.3.6.1.2.1.1.1.0 => SysDec
* OID - .1.3.6.1.2.1.1.5.0 => SysName
*.1.3.6.1.2.1.1.1.0
*.1.3.6.1.2.1.25.3.2.1.3.1
* => MIB explorer will be usefull here, as discussed in previous article
*/
String sysDescr = client.getAsString(new OID("1.3.6.1.2.1.25.3.2.1.3.1"));
System.out.println(sysDescr);
}
private void start() throws IOException {
TransportMapping transport = new DefaultUdpTransportMapping();
snmp = new Snmp(transport);
// Do not forget this line!
transport.listen();
}
/**
* Method which takes a single OID and returns the response from the agent as a String.
* @param oid
* @return
* @throws IOException
*/
public String getAsString(OID oid) throws IOException {
ResponseEvent event = get(new OID[]{oid});
if(event.getResponse() != null){
return event.getResponse().get(0).getVariable().toString();
} else {
return "no target";
}
}
/**
* This method is capable of handling multiple OIDs
* @param oids
* @return
* @throws IOException
*/
public ResponseEvent get(OID oids[]) throws IOException {
PDU pdu = new PDU();
for (OID oid : oids) {
pdu.add(new VariableBinding(oid));
}
pdu.setType(PDU.GET);
ResponseEvent event = snmp.send(pdu, getTarget(), null);
if(event != null) {
return event;
}
throw new RuntimeException("GET timed out");
}
/**
* This method returns a Target, which contains information about
* where the data should be fetched and how.
* @return
*/
private Target getTarget() {
Address targetAddress = GenericAddress.parse(address);
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString("public"));
target.setAddress(targetAddress);
target.setRetries(2);
target.setTimeout(5000);
target.setVersion(SnmpConstants.version1);
return target;
}
}
Здравствуйте, я пытаюсь выполнить процедуру Java в Oracle JVM. Эта процедура отправляет на принтер запрос SNMP, чтобы узнать его имя; он использует библиотеку SNMP4j. Я использую Oracle 19c, я скомпилировал эту процедуру с помощью javac --release 8, после того как загрузил библиотеку snmp4j-2.8.3.jar в базу данных с помощью loadjava, а затем загрузил саму процедуру. Затем я создал процедуру в sqlplusCREATE OR REPLACE Procedure Test_ink AS LANGUAGE JAVA NAME 'Get_ink_levels_devices.main (java.lang.String [])';
и установить разрешения exec dbms_java.grant_permission (grantee => 'ADMIN', permission_type => 'SYS: java.net.SocketPermission', permission_name => '192.168.115.77:161',permission_action =>' accept, connect, listen, resolve ');
и предоставил
GRANT JAVASYSPRIV TO Admin rights;
GRANT JAVAUSERPRIV TO Admin;
GRANT JAVAIDPRIV TO Admin;
exec dbms_network_acl_admin.create_acl('network_acl.xml','Test','ADMIN',TRUE,'connect',SYSTIMESTAMP,NULL)
exec DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE('network_acl.xml','ADMIN',TRUE,'connect',NULL,SYSTIMESTAMP,NULL)
exec DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL('network_acl.xml','*',1,65535);
Я запускаю процедуру так:
set serveroutput on;
call dbms_java.set_output (1000000);
exec Test_ink;
Но он не возвращает имя принтера, а возвращает "no traget", хотя, если я запускаю программу в консоли, она возвращает имя. Я не понимаю, что делаю не так. Я не указал необходимые разрешения для Java или проблема в другом?
Дополнение В общем, я пробовал выполнить удаленную отладку этой процедуры через SQL Developer с помощью CALL DBMS_DEBUG_JDWP.CONNECT_TCP. В результате я получил сообщениеThe debbuger has hit an exception breackpoint, but it cannot find the source file.Unable to find source file for package java.net,filename DualStackPlainDatagramSocketImpl.java.Project IdeConnections%23OEC.jpr and its dependencies have already been searched.
Насколько я понял, он не может найти файл с java-пакетом, так как он встроен в саму СУБД Oracle, тоже было сообщение
An unknown, invalid, or unsupported parameter or level was specified to call getsockopt or setsockopt.```
I took a simple procedure that simply sends a UDP diagram to a given address and port:
```import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class udp {
public static void main(String[] args){
System.out.println(udp.send("192.168.112.77","53","Test"));
}
public static String send(String ip,String port,String msg){
try{
int int_port=Integer.parseInt(port);
DatagramSocket ds = new DatagramSocket();
DatagramPacket dp = new DatagramPacket(msg.getBytes(), msg.length(), InetAddress.getByName(ip), int_port);
ds.send(dp);
ds.close();
return "Successfully";
}catch(Exception e){
return "Failed";
}
}
}
И в случае успеха выводит сообщение и снова в консоли все нормально, при выполнении в базе данных возвращает "Failed". В SQL Developer снова та же ошибка. Я не понимаю Java и просто пытаюсь, но, исходя из всего этого, могу ли я предположить, что это какая-то ошибка в Oracle JVM при работе с UDP, у меня JDK версии 1.8.0_201 в Oracle, или все еще проблема с разрешениями Java, но я не могу себе представить, в каких, поскольку я разрешил все, что возможно с точки зрения работы с сетью Java.