javadicomdcm4che

Connecting to dcm4chee using dcm4che from a JAVA program


Update

I dug deeper in dcm4che's source code and found that an IncompatibleConnectionException is thrown if either

I don't know what it means that a connection is "installed" but this flag can be set manually, so I set it for both the local and remote connections to true (even checked them with getInstalled() whether they are "installed" - and yes they are now - previously this property was null).

And as to the protocols, they weren't specified, so for both connections I set them to DICOM.

Results: I still get the same Exception.


I'd like to establish a DICOM association between dcm4chee (2.18.3) and my JAVA application using the dcm4che (5.12.0) toolkit.

The problem is that it doesn't seem to be any documentation available on how to use dcm4che in a JAVA application, so all I can do is read dcm4che's source code and try to figure out what its classes and methods are for, but I'm stuck. If someone already has a working example it would be very helpful.

So far I have:

import org.dcm4che3.net.ApplicationEntity;
import org.dcm4che3.net.Association;
import org.dcm4che3.net.Connection;
import org.dcm4che3.net.Device;
import org.dcm4che3.net.pdu.AAssociateRQ;
import org.dcm4che3.net.pdu.PresentationContext;

...

ApplicationEntity locAE = new ApplicationEntity();
locAE.setAETitle("THIS_JAVA_APP");

Connection localConn = new Connection();
localConn.setCommonName("loc_conn");
localConn.setHostname("localhost");
localConn.setPort(11112);
localConn.setProtocol(Connection.Protocol.DICOM);
localConn.setInstalled(true);
locAE.addConnection(localConn);

ApplicationEntity remAE = new ApplicationEntity();
remAE.setAETitle("DCM4CHEE");

Connection remoteConn = new Connection();
remoteConn.setCommonName("rem_conn");
remoteConn.setHostname("localhost");
remoteConn.setPort(11112);
remoteConn.setProtocol(Connection.Protocol.DICOM);
remoteConn.setInstalled(true);
remAE.addConnection(remoteConn);

AAssociateRQ assocReq = new AAssociateRQ();
assocReq.setCalledAET(remAE.getAETitle());
assocReq.setCallingAET(locAE.getAETitle());
assocReq.setApplicationContext("1.2.840.10008.3.1.1.1");
assocReq.setImplClassUID("1.2.40.0.13.1.3");
assocReq.setImplVersionName("dcm4che-5.12.0");
assocReq.setMaxPDULength(16384);
assocReq.setMaxOpsInvoked(0);
assocReq.setMaxOpsPerformed(0);
assocReq.addPresentationContext(new PresentationContext(
    1, "1.2.840.10008.1.1", "1.2.840.10008.1.2"));

Device device = new Device("device");
device.addConnection(localConn);
device.addApplicationEntity(locAE);

Association assoc = locAE.connect(remAE, assocReq);

but I don't know whether I'm on the right path doing it.

The error I get:

org.dcm4che3.net.IncompatibleConnectionException: No compatible connection to DCM4CHEE available on THIS_JAVA_APP
at org.dcm4che3.net.ApplicationEntity.findCompatibelConnection(ApplicationEntity.java:646)
at org.dcm4che3.net.ApplicationEntity.connect(ApplicationEntity.java:651)

Solution

  • Here is the working code: (I don't know if it's the minimal solution, feel free to experiment with it...)

    ApplicationEntity locAE = new ApplicationEntity();
    locAE.setAETitle("THIS_JAVA_APP");
    locAE.setInstalled(true);
    
    Connection localConn = new Connection();
    localConn.setCommonName("loc_conn");
    localConn.setHostname("localhost");
    localConn.setPort(11112);
    localConn.setProtocol(Connection.Protocol.DICOM);
    localConn.setInstalled(true);
    locAE.addConnection(localConn);
    
    ApplicationEntity remAE = new ApplicationEntity();
    remAE.setAETitle("DCM4CHEE");
    remAE.setInstalled(true);
    
    Connection remoteConn = new Connection();
    remoteConn.setCommonName("rem_conn");
    remoteConn.setHostname("localhost");
    remoteConn.setPort(11112);
    remoteConn.setProtocol(Connection.Protocol.DICOM);
    remoteConn.setInstalled(true);
    remAE.addConnection(remoteConn);
    
    AAssociateRQ assocReq = new AAssociateRQ();
    assocReq.setCalledAET(remAE.getAETitle());
    assocReq.setCallingAET(locAE.getAETitle());
    assocReq.setApplicationContext("1.2.840.10008.3.1.1.1");
    assocReq.setImplClassUID("1.2.40.0.13.1.3");
    assocReq.setImplVersionName("dcm4che-5.12.0");
    assocReq.setMaxPDULength(16384);
    assocReq.setMaxOpsInvoked(0);
    assocReq.setMaxOpsPerformed(0);
    assocReq.addPresentationContext(new PresentationContext(
        1, "1.2.840.10008.1.1", "1.2.840.10008.1.2"));
    
    Device device = new Device("device");
    device.addConnection(localConn);
    device.addApplicationEntity(locAE);
    
    Executor exec = (Runnable command) -> {};
    device.setExecutor(exec);
    
    Association assoc = locAE.connect(localConn, remoteConn, assocReq);
    

    And the relevant dcm4chee log:

    2018-03-02 23:21:42,832 INFO  THIS_JAVA_APP->DCM4CHEE (TCPServer-1) [org.dcm4cheri.net.FsmImpl] received AAssociateRQ
        appCtxName: 1.2.840.10008.3.1.1.1/DICOM Application Context Name
        implClass:  1.2.40.0.13.1.3
        implVersion:    dcm4che-5.12.0
        calledAET:  DCM4CHEE
        callingAET: THIS_JAVA_APP
        maxPDULen:  16378
        asyncOpsWindow: 
        pc-1:   as=1.2.840.10008.1.1/Verification SOP Class
            ts=1.2.840.10008.1.2/Implicit VR Little Endian
    2018-03-02 23:21:42,843 INFO  THIS_JAVA_APP->DCM4CHEE (TCPServer-1) [org.dcm4cheri.net.FsmImpl] sending AAssociateAC
        appCtxName: 1.2.840.10008.3.1.1.1/DICOM Application Context Name
        implClass:  1.2.40.0.13.1.1.1
        implVersion:    dcm4che-1.4.34
        calledAET:  DCM4CHEE
        callingAET: THIS_JAVA_APP
        maxPDULen:  16352
        asyncOpsWindow: 
        pc-1:   0 - acceptance
            ts=1.2.840.10008.1.2/Implicit VR Little Endian
    

    After you have the association, see this other post for how to perform a C-FIND.