Problem
You get org.snmp4j.agent.DuplicateRegistrationException because there can be only one ManagedObject in the ContextScope. Each registration assigns ManagedObject value to the MOContextScope. Second registration tries to set second object to the contextScope. The scope is already filled and thus exception is thrown.
Althow each scalar value SHOULD end up with .0. You may check any MIB browser like iReasoning and pick any value. If this value is scalar - trailing zero is appended automaticaly despite the fact it is not mentioned in MIB-file. So the most "correct" way is to use 4.1 solution.
Solution 1 - own MOScalar
Write your own MOScalar. With tinier bounds.
You should overwrite getLowerBound, getUpperBound, isLowerIncluded, isUpperIncluded to get separate contextScopes for your objects.
I would suggest to return Scalar OID every time and include both boundaries.
Upper and lower boundaries better return same OID you've settled.
Solution 2 - own MOServer
Write your own MOServer. With blackJack and others...
Mostly you can simply copypaste code despite this one
private SortedMap<MOScope, ManagedObject> registry;
It should look like this
private SortedMap<MOScope, Set<ManagedObject>> registry;
And it would affect registration, unregistration and other logic.
DefaultMOServer - 678 lines incl. comments. In fact you should fix several classes:
query.matchesQuery(object)
private boolean matchesQuery(MOQuery query, ManagedObject object) {
if ((query.matchesQuery(object)) && object.getScope().isOverlapping(query.getScope()))
if (object instanceof MOScalar) {
MOScalar moScalar = (MOScalar) object;
return query.getLowerBound().compareTo(moScalar.getID()) <= 0 &&
query.getUpperBound().compareTo(moScalar.getID()) >= 0;
} else {
return true;
}
return false;
}
protected void fire...Event(ManagedObject objects, MOQuery query) {
protected void fire...Event(Set<ManagedObject> objects, MOQuery query) {
if (lookupListener != null) {
for (ManagedObject mo : objects) {
ManagedObject other = lookup(new DefaultMOQuery(contextScope));
Set<ManagedObject> other = lookup(new DefaultMOQuery(contextScope), false);
And so on...
Solution 3 - Tables
Use table rows.
You can add a table and append rows.
You would be able to access cells as the
<tableEntryOID>.<columnSubID>.<rowIndexOID>
You may use this question as tutorial.
Solution 4 - OIDs fixup
Make you oid's use different contextScopes.
Solution 4.1
Adding trailing zero
agent.registerManagedObject(
MOScalarFactory.createReadOnly(
new OID(oid.getOid()).successor(),
oid.getValue()
)
);
This will append .0 to the same-level properties.
snmpget -v2c -c public localhost:2001 oid.getOid().0
Also any MIBbrowser will append .0 to each scalar oid defined in the MIB-file. You may check it with iReasoning as the most popular browser. Even hrSystemUptime (.1.3.6.1.2.1.25.1.1 - see left bottom) is requested as hrSystemUptime.0 (.1.3.6.1.2.1.25.1.1.0) on the top.
Solution 4.2
Separate OID at the base.
static final OID sysDescr1 = new OID("1.3.6.1.4.1.5.6.1.8.9"),
sysDescr2 = new OID("1.3.6.1.4.1.5.6.2.2.5");
Fix the database OIDs to get separate contextScopes.
In addition
You can try reading SNMP4J-Agent-Instrumentation-Guide.pdf. This didn't helped me btw.
You can attach the sources to your IDE to read about zero trailer and other nuances. This helped me a lot to get more info about DefaultMOServer.
Correct pom.xml import to get latest version
<repositories>
<repository>
<id>SNMP4J</id>
<url>https://oosnmp.net/dist/release/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j-agent</artifactId>
<version>2.3.2</version>
</dependency>
</dependencies>