johvargas / sfdc-wsc

Automatically exported from code.google.com/p/sfdc-wsc
0 stars 0 forks source link

Enhancement Request: Provide Soap Interfaces (at least for EnterpriseConnection) #52

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
The short story:

Life would be much easier if EnterpriseConnection were based on an interface 
like RestConnection was. Furthermore, the more of the generated code that can 
be based on generated interfaces, the better. But at least EnterpriseConnection 
would make my day.

The long story:

I have two big needs in my application that are solved VERY simply. The first 
big need is the ability to unit test by mocking interfaces. The second big need 
is the ability to have a pool of EnterpriseConnections that I can borrow from 
and return to.

Now, granted, both are possible without interfaces. But both are DRASTICALLY 
easier with interfaces.

For example: I'm using commons-pool to pool connections. Now, I can carry 
around a bulky pool object of EnterpriseConnections and borrow from the pool 
and return to the pool when I'm done. Or, I can do something much more 
lightweight and mimicking the JDBC pattern that all of my developers are used 
to:

- A ConnectionSource with one getConnection() method that returns an connection
- A close() method on that connection that returns the connection to the pool 
(doesn't actually close it / log out)

I used my IDE to extract an interface from EnterpriseConnection (I named it 
IEnterpriseConnection) and recompiled EnterpriseConnection to implement 
IEnterpriseConnection, then put those two classes back in the JAR file. Then I 
created an interface in my project called SalesforceConnection that extended 
IEnterpriseConnection and included a close() method. Then I created a 
PooledSalesforceConnection that wrapped an IEnterpriseConnection, delegated all 
method calls to the wrapped IEnterpriseConnection, and returned itself to the 
pool when the close() method was called. It works beautifully, and that pattern 
was only made possible (well ... easily possible) because of the 
IEnterpriseConnection interface.

Another example: We use EasyMock to mock interfaces in our unit testing. With a 
RestConnection, which is an interface, I can just mock it right up, and any 
unexpected method calls will throw errors. With an EnterpriseConnection, I can 
still technically mock it (with a few extra libraries, you can mock non-final 
abstract or concrete classes in EasyMock), but if I don't tell it to expect a 
method call and the method is called, it will delegate to the underlying 
EnterpriseConnection, which is a concrete implementation. Nasty stuff.

With the IEnterpriseConnection I created, now I can just mock the interface 
like I mock an interface, and it's a much easier process.

So, I was able to drastically simplify what all I needed to do by creating an 
IEnterpriseConnection interface and recompiling EnterpriseConnection to 
implement it. If sfdc-wsc could just ship automatically having some of its key 
objects (namely EnterpriseConnection) implementing interfaces, that would be a 
huge improvement, in my opinion.

Original issue reported on code.google.com by nicholas...@puresafety.com on 6 Mar 2012 at 9:55

GoogleCodeExporter commented 8 years ago
Can I get some feedback on this? When is the next anticipated release for 
sfdc-wsc? Any idea how easy/difficult it would be to get this in the next 
release?

Original comment by nicholas...@puresafety.com on 3 Jul 2012 at 9:58

GoogleCodeExporter commented 8 years ago
Hi.

I understand your problem and agree – it would make unit-testing alot easier 
if you could mock the SFDC api. Problem is, the EnterpriseConnection (and 
PartnerConnection) classes are generated from the wslds. If an interface is 
required too, the wsdlc tool would need to handle this specifically. 
Imho the interface should be called EnterpriseConnection and the implementation 
eg  EnterpriseConnectionImpl. Not possible without breaking the current 
contract.

But you can do as I've done. Consider Salesforce as a third party legacy 
backend system that you need to hide behind a facade. The facade is an 
interface called e.g. SalesforceApi, containing only the operations your 
application needs. Decoupling. This interface is fixed towards your needs. In 
my case it contains operations like upsert, update and create.

The most obvious implementation of the interface (eg called 
SalesforceApiWscImpl) is nothing but a delegate. But here you have an interface 
facade and implementation separated from the interface.

Now you can create your own intersting implementations of this interface.

I have 2 that I “chain” in front of the SFDC delegate. One that handles 
statistics logging of calls and objects being updated in SFDC. Another in front 
that splits any array parameter into sub-arrays of max 200 items to call back 
with...

Original comment by jesperudby on 25 Jan 2013 at 10:54

GoogleCodeExporter commented 8 years ago

Original comment by jesperudby on 31 Jan 2013 at 8:29

GoogleCodeExporter commented 8 years ago

Original comment by jesperudby on 31 Jan 2013 at 8:36

GoogleCodeExporter commented 8 years ago
While normally I agree that it should be named EnterpriseConnection and 
EnterpriseConnectionImpl, I knew that would break the contract, hence why I 
switched to the C# standard and went with IEnterpriseConnection and 
EnterpriseConnection.

The IEnterpriseConnection thing worked for a while ... but after so many times 
of regenerating the WSDL and then regenerating the code, I ended up using CGLib 
and creating a proxy. The connection is "retrieved" from the pool and then 
"closed," which actually just returns it to the pool. Same model as JDBC 
connection pooling. And it works really well, too. I was quite pleased.

I understand that the WSDL defines EnterpriseConnection, but I'm still not 
quite sure why SFDC, while turning the WSDL into code, couldn't say "I'll 
create this EnterpriseConnection class, but I'll also create this interface 
that looks just like it that it implements." I must say, for many users, this 
may make unit testing significantly easier, or even possible in situations 
where it wasn't previously.

Original comment by nicholas...@puresafety.com on 31 Jan 2013 at 9:02

GoogleCodeExporter commented 8 years ago
Well, I don't like prefixing my interfaces with I :-)

Why use CGLib?

I just create an interface with the methods I need, eg.:

public interface SalesforceCoreApi {
    SaveResult[] create(SObject[] sObjects) throws Exception;
    SaveResult[] update(SObject[] sObjects) throws Exception;
    UpsertResult[] upsert(String externalIDFieldName, SObject[] sObjects) throws Exception;
    DeleteResult[] delete(String[] ids) throws Exception;
}

Then I have a default implementation - just a delegate eg.:

public class SalesforceCoreApiWscImpl implements SalesforceCoreApi {
    private final EnterpriseConnection con;

    public SalesforceCoreApiWscImpl(EnterpriseConnection con) {
        this.con = con;
    }

    @Override
    public DeleteResult[] delete(String[] ids) throws ConnectionException {
        return con.delete(ids);
    }

    @Override
    public SaveResult[] update(SObject[] sObjects) throws ConnectionException {
        return con.update(sObjects);
    }

    @Override
    public UpsertResult[] upsert(String externalIDFieldName, SObject[] sObjects) throws ConnectionException {
        return con.upsert(externalIDFieldName, sObjects);
    }

    @Override
    public SaveResult[] create(SObject[] sObjects) throws ConnectionException {
        return con.create(sObjects);
    }   
}

Then I have a factory that provides me with the proper implementation, does the 
necessary connection stuff. Anytime I'm able to create stubs that can be used 
for unit-testing.

KISS ;-)

Best regards

Jesper Udby

PS: I have no relation with SFDC, just agreed to be a committer of the sfdc-wsc 
tool. It might not happen though, as there seem to be some confusion as to what 
is actually the proper source. See: 
http://boards.developerforce.com/t5/Java-Development/Which-WSC/td-p/561415
I am using the wsc tool and above method in production at at medium-large SFDC 
customer in different integration components.

Original comment by jesperudby on 2 Feb 2013 at 9:41