So you want to be a hero?
You had better be prepared for a little heroics if you want to use the QuickBooks SDK with Java because it isn’t exactly straightforward. I saw a few mentions of people having done this, but certainly didn’t find any tutorials. Maybe I will be the first person on the planet to write this up. BOW TO YOUR NEW GOD!
Anyway, the problem is that the QBSDK is done with Microsoft’s COM and Java has no built-in COM support. I should mention that you can use Java with the Online Edition or apparently by setting up a Tomcat server and sending qbXML through a SOAP-to-COM pipe or something like that. In my case, I had a bunch of existing Java code that I wanted to connect as directly as possible to QuickBooks – preferably using QBFC.
If you don’t know what I’m talking about with QBSDK, qbXML, and QBFC then you should read this informative tutorial.
After hunting around the web, I found a free library called JACOB: Java-COM Bridge. The theory is that I could go from Java -> JACOB -> QBFC -> QuickBooks. I managed to create a proof of concept for this theory that I will begin sharing with you now.
SETUP
- Obviously, install QuickBooks, run its updates, and create a test company file (I’m using QuickBooks Premier Nonprofit Edition 2007)
- Sign up with the Intuit Developer Network and then download/install the SDK. Note that you must say “yes” to installing the .NET stuff or the install will fail. (I’m using QBSDK 7.0)
- Download and extract JACOB (I’m using version 1.14)
- Being on a 32-bit OS, I copied the x86 JACOB DLL (
jacob-1.14-x86.dll
) intoC:\WINDOWS\system32
- For Eclipse users, go to the
Java Build Path
property, click theAdd External JARs
button, and add jacob.jar to your project. For non-Eclipse users, make sure that the JAR is in your CLASSPATH.
NOTES ABOUT JACOB
Obviously everything you do with the QBSDK must be enveloped by JACOB API calls. The main beasts in JACOB seem to be Dispatch
and Variant
. Basically, you’ll use Dispatch
to call functions on COM objects, and Variant
to serve as parameters and outputs to those functions.
While JACOB seems to work well for me so far, the project lacks documentation of the HOWTO/tutorial variety. By cruising the web for examples and looking over the API, you can sort of figure out how things work. As I was wrestling with it, I stumbled across a QBFC wrapper for Ruby. Looking at the project’s source code helped me figure out a couple of things in the JACOB-QBFC connection.
One thing that JACOB lacks is the ability to lookup COM constants. Some of the QBFC functions require you to pass in one of their constants – hard to do when you can’t access them. The workaround for this is in the How can I get the value of constants? question in the JACOB FAQ. In short, you are supposed to use the Visual Basic editor in Excel to open the “object browser”, search for the constant, read its value, then code it into your program. Not exactly an elegant solution, but oh well. Note that when you’re in the object browser, you’ll need to go to Tools -> References
and add the QBFC7Lib
.
THE FIRST TIME HURTS
The first time you connect to QuickBooks through your application, you need to have QuickBooks already running. If you do not, then you’ll get an error message like:
This application is not allowed to log into this QuickBooks company data file automatically. The QuickBooks administrator can grant permission for an automatic login through the Integrated Application preferences.
The reason is that QuickBooks needs to pop open a dialog box and ask you if the application is really allowed to connect. After you’ve registered your application with QuickBooks, you’ll be able to access the data without the need to open it first.
SHOW ME THE CODE!
This code assumes that you have some vendors defined. If all goes according to plan, then it should print out all your defined vendors. Note that I am not doing all the various error, status, and type checking that the documentation mentions.
import com.jacob.com.*; public class Foo { public static void main(String[] args) { System.out.println("Hello world!"); // QBFC constants looked up using the object browser Variant ctLocalQDB = new Variant(1); Variant omDontCare = new Variant(2); // major and minor version of qbXML used to talk to QuickBooks Variant qbXMLMajor = new Variant(6); Variant qbXMLMinor = new Variant(0); // location of the company file to access String qbFile = "C:\\Documents and Settings\\rdavis\\Desktop\\FfAMETest.QBW"; // connect to QuickBooks Dispatch qbsm = new Dispatch("QBFC7.QBSessionManager"); Dispatch.call(qbsm, "OpenConnection2", "", "My Sample App", ctLocalQDB); Dispatch.call(qbsm, "BeginSession", qbFile, omDontCare); // build and execute a request to obtain all vendors Dispatch msgSet = Dispatch.call(qbsm, "CreateMsgSetRequest", "US", qbXMLMajor, qbXMLMinor).toDispatch(); Dispatch.call(msgSet, "AppendVendorQueryRq"); Dispatch resSet = Dispatch.call(qbsm, "DoRequests", msgSet).toDispatch(); Dispatch resList = Dispatch.get(resSet, "ResponseList").toDispatch(); int count = Dispatch.get(resList, "Count").getInt(); for (int i = 0; i < count; i++) { Dispatch res = Dispatch.call(resList, "GetAt", new Variant(i)).toDispatch(); // blindly assume that we have a vendor response Dispatch vendList = Dispatch.get(res, "Detail").toDispatch(); int vcount = Dispatch.get(vendList, "Count").getInt(); for (int j = 0; j < vcount; j++) { Dispatch vend = Dispatch.call(vendList, "GetAt", new Variant(j)).toDispatch(); Dispatch dname = Dispatch.get(vend, "Name").toDispatch(); String name = Dispatch.call(dname, "GetValue").getString(); System.out.println("Vendor: " + name); } } // close the QuickBooks connection Dispatch.call(qbsm, "EndSession"); Dispatch.call(qbsm, "CloseConnection"); System.out.println("Goodbye world!"); } }
CONCLUSION
Using QBFC is already a somewhat verbose process and running it through JACOB certainly doesn't make the code more terse. Hopefully I'll be able to create my own little API to shield most of my code from needing to mess with all these Dispatch
es. My needs might be simple enough that I can wrap all the ugly stuff in a few function calls. After I get really down and dirty with QBFC I may write another post detailing my exploits.
Thanks for the post. This was just the info I needed to get started interfacing a Java app to QuickBooks. Ya gotta love Google. I’ll keep an eye out for any future posts you do on this subject.
Thanks
After spending days on Google I’ve finally found someone who’s doing something similar to what I want to do.
Scenario:
There is a clinic that sells glasses, contact lenses, eye drops, etc. Patients buy these things and the sale is recorded on the clinic’s browser-based application. That application is used for all their patient management and so on, they don’t want to have to open up QuickBooks to record the sale obviously. So I’ve been asked to write a module to add onto their Java-based web application that will take each transaction and pop it into QuickBooks. It only needs to input transactions, it never needs to read anything out of QuickBooks
The first thing I’d like to ask is do I go for the approach of entering each sale into QuickBooks transaction-by-transaction, or do I accumulate the sales for the day and then do a dump of the data into QuickBooks, OR do I accumulate the data for the day and then open up QuickBooks and do an import (that’s not very elegant).
Secondly, what have been your findings on how to do this? I’m new to QuickBooks, and frankly feel a bit intimidated by the idea of attempting this, although I’m a pretty sharp programmer in both Java and PHP.
Paul: as a disclaimer, I don’t have much experience with Java-QuickBooks interaction aside from the proof of concept that I posted here. But as you mentioned, I can see two basic ways to approach it: 1) incorporate the QBSDK code into your Java webapp and add the transactions to QuickBooks in real time, or 2) run a batch job on an hourly/daily/whatever basis that imports any unprocessed transactions.
If you’re going to do (1), then you might want to research the QuickBooks Online Edition. The reason is that I think this Java-COM bridge stuff needs everything (QuickBooks, the Java app, the QBSDK) to be installed on the same Windows box. With the Online Edition, I think you can talk to QuickBooks remotely using SOAP.
For (2), you could set something up similar to the example I listed in this blog post. I guess you’d write a Java program that would query the clinic’s database for new transactions, then import them into QuickBooks via the Java-COM bridge.
If I were you, I would want to do something along the lines of (1) because you keep your code centralized and there is potentially less complexity with fewer points of failure. The issues would probably be the cost of the Online Edition, figuring out to how to get it set up and configured, and trying to get the Java webapp to talk to it.
Good luck!
Great Post! While messing around I decided to code-up a sample for performing an insert. the code is as follows:
public static void main(String[] args) {
// connect to QuickBooks
Dispatch qbsm = new Dispatch(“QBFC7.QBSessionManager”);
Dispatch.call(qbsm, “OpenConnection2”, “”, “My Sample App”, ctLocalQDB);
System.out.println(“Starting Session 1”);
String qbFile = “C:\\test\\sample_service-based business.qbw”;
Dispatch.call(qbsm, “BeginSession”, qbFile, omDontCare);
Dispatch msgSet = Dispatch.call(qbsm, “CreateMsgSetRequest”, “US”, qbXMLMajor, qbXMLMinor).toDispatch();
Dispatch setMsg = Dispatch.call(msgSet, “AppendVendorAddRq”).toDispatch();
Dispatch name = Dispatch.get(setMsg, “Name”).toDispatch();
Dispatch.call(name, “setValue”, “testing”);
Dispatch cName = Dispatch.get(setMsg, “CompanyName”).toDispatch();
Dispatch.call(cName, “setValue”, “testing company”);
Dispatch address = Dispatch.get(setMsg, “VendorAddress”).toDispatch();
Dispatch addrline = Dispatch.get(address, “Addr1”).toDispatch();
Dispatch.call(addrline, “setValue”, “address”);
Dispatch addrCity = Dispatch.get(address, “City”).toDispatch();
Dispatch.call(addrCity, “setValue”, “City”);
Dispatch addrState = Dispatch.get(address, “State”).toDispatch();
Dispatch.call(addrState, “setValue”, “State”);
Dispatch addrZip = Dispatch.get(address, “PostalCode”).toDispatch();
Dispatch.call(addrZip, “setValue”, “59236”);
Dispatch resSet = Dispatch.call(qbsm, “DoRequests”, msgSet).toDispatch();
Dispatch resList = Dispatch.get(resSet, “ResponseList”).toDispatch();
// close the QuickBooks connection
Dispatch.call(qbsm, “EndSession”);
Dispatch.call(qbsm, “CloseConnection”);
System.out.println(“Ending Session 1”);
}
the corresponding insert would look something like this in C#
vendorAddRequest.Name.SetValue(“ACME, Inc”);
vendorAddRequest.CompanyName.SetValue(“ACME, Inc”);
vendorAddRequest.VendorAddress.Addr1.SetValue(“123 Some St”);
vendorAddRequest.VendorAddress.City.SetValue(“Somecity”);
vendorAddRequest.VendorAddress.State.SetValue(“ST”);
vendorAddRequest.VendorAddress.PostalCode.SetValue(“12345);
Do you have any update about the Java API?
I am using QuickBooks Simple Start 2008, I have to set authFlags. The following is VB code from guide:
======================================================
Dim authFlags As Long
authFlags = 0
authFlags = authFlags Or &H8&
authFlags = authFlags Or &H4&
authFlags = authFlags Or &H2&
authFlags = authFlags Or &H1&
authFlags = authFlags Or &H80000000
Dim qbXMLCOM As QBXMLRP2Lib.RequestProcessor2
Dim prefs As QBXMLRP2Lib.AuthPreferences
Set prefs = qbXMLCOM.AuthPreferences
prefs.PutAuthFlags (authFlags)
======================================================
How can I covert the code into java using JACOB?
Thanks a lot.
Arden
my email: tomcatacec@yahoo.ca
Finally, I make it works.
==============================================================
long authFlags = 0;
authFlags = authFlags | SupportQBSimpleStart;
authFlags = authFlags | SupportQBPro;
authFlags = authFlags | SupportQBPremier;
authFlags = authFlags | SupportQBEnterprise;
authFlags = authFlags | ForceAuthDialog;
Variant qbAuthFlags = new Variant();
qbAuthFlags.putLong(authFlags);
Dispatch qbsm = new Dispatch(“QBFC7.QBSessionManager”);
Dispatch auth = Dispatch.call(qbsm, “QBAuthPreferences”).toDispatch();
Dispatch.call(auth, “PutAuthFlags”, qbAuthFlags);
I was trying to get the names of my customers and then some data from custom defined fields, it was annoyingly painful and here is the most useful place I found, so the code to do it is below.
DataExtRet is a list of all the custom data you have so you have to go through the list and find what you’re wanting.
Also if you’re wanting to access private information the OwnerId has to be the guid of the data and not 0.
Dispatch currentSession = new Dispatch(“QBFC7.QBSessionManager”);
Dispatch.call(currentSession, “OpenConnection2”, “”, “My Sample App”, ctLocalQDB);
Dispatch.call(currentSession, “BeginSession”, qbFile, omDontCare);
Dispatch msgSet = Dispatch.call(currentSession, “CreateMsgSetRequest”, “UK”, qbXMLMajor, qbXMLMinor).toDispatch();
Dispatch req = Dispatch.call(msgSet, “AppendCustomerQueryRq”).toDispatch();
Dispatch inc = Dispatch.get(req, “IncludeRetElementList”).toDispatch();
Dispatch.call(inc,”Add”, “Name”);
Dispatch.call(inc,”Add”, “DataExtRet”);
Dispatch owner = Dispatch.get(req, “OwnerIDList”).toDispatch();
Dispatch.call(owner,”Add”, “0”);
Dispatch resSet = Dispatch.call(currentSession, “DoRequests”, msgSet).toDispatch();
Dispatch resList = Dispatch.get(resSet, “ResponseList”).toDispatch();
Support for Java by Intuit is a joke.
Did you know that the Quickbooks SDK actually points to this page in their Java section???
This is taken from the Quickbooks SDK Programming manual, regarding java:
*************************************
Using Java with QB SDK
If you want to use Java with the QB SDK, you need to use a Java to COM bridge, for example the Jacob bridge product. For more information, search the web, and take a look at the blog Using the QuickBooks SDK via JACOB Java-Com Bridge.from Theoden’s Coding Tips.
*******************************************
What a joke. Very professional on your part Intuit.
While Theoden has developed working method, lets face it, this is a pain in the butt to use.
Don’t get me wrong, we should all be thankful he actually went and did this work; and that he offered to create a class wrapper to facilitate use. However, I’m guessing that he must be tied up in other projects, since there is no sign of this API.
I’ve created one. It uses qbXML instead of QBFC, which I believe is the best way to go for QBJava interaction. Simply create the XML file, pass it as a String to my program along with the path to the company file you want to modify and that’s it. The program will pass along Quickbooks reply.
If interested, contact me at temporal_69-qb*yahoo.com (substitute the * for @)
Wow… I had no idea that I was linked to in the SDK manual. The story is that a co-worker wound up writing the API, reworking it several times in the year since I originally made this post. Since Intuit has apparently passed the Java buck to this blog, I’ll make inquiries about open-sourcing the code. I’ll update you with a comment in a day or so…
Unfortunately it looks like I will not be able to open-source the code 🙁 Perhaps one day Intuit will develop their own Java API. JACOB is licensed under the LGPL so that would make it easier on them I’d imagine…
Don’t worry theoden I undestand…
Btw… I have like a week searching for something that make me understand what the hell is happening around quickbooks.
I made a complete website using Spring MVC and Spring Webflow (java)… now I have to integrate it with quickbooks. Demo I just found things for .net and well I was like agh damn this is getting hot lol…
well this was pretty god for me… thinking that is the first time that something that work with java is working… 🙂
So you did pretty god….
I will continue using searching, cuz I almost sure that I have to use the webconnect for quickbooks, but I still don’t have any idea about how I can integrate with it…
For anyone interested that would like a more Java friendly QBFC like interface I have written a program (about 2 years ago) that takes a QBFC.tlh file and generates a code for a DLL (compiled with Visual Studio Express C++) that wraps the COM and code for a JAR that wraps the DLL. It could probably use some tweaking if the API has changed in newer versions of QuickBooks, I think it was build on 6.0. It’s provided as is, and if it needs fixing you’ll probably have to learn little about COM. Consider it under a BSD license (no license text or copyrights appear in the code). Attribution would be nice at the very least. Feel free to come up with a better name for it. Code is found at http://nutzy.net/downloads/CashQ%20Generator.zip and a sample usage at http://nutzy.net/downloads/CashQExample.java.
Almost forgot some code that is needed: http://nutzy.net/downloads/CashQ.zip. This is the fully generated Java part of the source code (most of which is regenerated by the previous code). Some of the files in here are assumed to already exist when the Generator runs (like the files in the COM directory). There may be others however in the root (over 1000 files in there) but I have forgotten for sure. So when the generator runs it points to this directory to store files in with the “hard coded” files preexisting. QBBase.java might be one of them (the lower level base classes are the best candidates hints from memory I can give at the present).
Sorry one last thing. Improvements over JACOB include the fact that you get Java Enums to represent the COM enums. If you use an IDE you get full code completion on the whole API, no guessing the strings of method names. I’ve tried to keep memory management to a minimum. Here’s most of the useful info out of the “manual” I wrote:
CashQ provides access to the QBFC API by wrapping the COM objects using JNI.
Since COM is used it must be initialized before accessing any of the QBFC
classes and methods, then when done it must be uninitialized to free up the
resources used by COM. COM must be initialized/uninitialized for each thread
of your application separately. Use the static methods COM.initialize() and
COM.uninitialize() at the start and end of each thread where QBFC classes and
methods may be used.
All methods in CashQ, even constructors, have the possibility of errors related
to failures at the COM level. Due to this, every method and constructor may throw
a Java exception named COMException. This exception subclasses RuntimeException
and provides access to the integer HRESULT code and string error message retrieved
from COM. Use the toString() method to retrieve a nicely formatted String that
includes the hexadecimal version of the HRESULT code with the error message. To
retrieve the code and message by themselves use getHRESULT() and getMessage().
Since CashQ uses COM it must track references to COM objects that must be released
when you are done with them. This extra memory clean up has been kept to a minimum.
Only the following classes need to be released after use: QBSessionManager,
QBOESessionManager, MsgSetRequest, MsgSetResponse, SubscriptionMsgSetRequest, and
SubscriptionMsgSetResponse. All other references to COM objects are child
references of one of these six classes and will be released when the parent
instance is released. Call the release() method when you are finished with an
instance of one of these classes.
The naming of classes and methods in CashQ closely follow the original naming in
QBFC with a few exceptions. Instead of accessing functionality through interfaces
such as ICheckQuery the corresponding CashQ Java class would be named CheckQuery
without the “I” prefix. Method names have been changed to match Java naming
conventions by making the first character of the name lower case. For example,
the “AppendCheckQueryRq” method from MsgSetRequest is now “appendCheckQueryRq”.
Lastly any methods that begin with “Put” will begin with “set” instead.
There are four methods that in the original QBFC API use return values using
parameters, either by pointers in C++ or out parameters in C#. Since Java does
not support returning values through parameters four special classes were made
to return the values from these methods. Each class simply contains getters
for each parameter from the original QBFC function call. They are as follows:
QBSessionManager.getVersion() returns QBVersion
MsgSetRequest.verify() returns QBErrorMessage
QBDateTimeType.getTimeZone() returns QBTimeZone
QBTimeIntervalType.getValue() returns QBTimeInterval
Guess I shouldn’t post when exhausted here is the CPP code similar to the Java code I think there are “hard coded” class files present, but the majority are regenerated. Also created a small CPP project to generate the TLH file to use. http://nutzy.net/downloads/CashQ_CPP.zip and http://nutzy.net/downloads/create_tlh.zip
Has anyone had any luck using the QBXML library with Java/Jacob vs using the QBFC library? I’ve generated the Jacob stubs against the type library QBXMLRP2 using the latest version of jacob and jacobgen. I’ve tried the following code without success. It always dies when attempting to call any of AuthPreferences methods with “Can’t map name to dispid”. I was trying to avoid having to expose the full QBFC COM api, so that’s why I’m trying to go with the supposedly simpler QBXML api.
Here’s the code:
RequestProcessor2 rp = null;
String ticket = null;
String response = null;
try {
rp = new RequestProcessor2();
rp.openConnection2(APPLICATION_ID, APPLICATION_NAME, QBXMLRPConnectionType.localQBD);
int authflags = 0;
authflags = authflags | 0x01;
AuthPreferences authPref = rp.authPref();
authPref.putUnattendedModePref(QBXMLRPUnattendedModePrefType.umpRequired);
authPref.putAuthFlags(authflags);
ticket = rp.beginSession(
//”C:/Documents and Settings/All Users/Documents/Intuit/QuickBooks/Company Files/EXAMPLE.QBW”,
“”,
QBFileMode.qbFileOpenDoNotCare);
response = rp.processRequest(ticket, request);
logger.info(“Response:\n” + response);
} catch (Exception e) {
logger.error(“Error with request”, e);
return;
} finally {
if (rp != null) {
if (ticket != null) {
rp.endSession(ticket);
}
rp.closeConnection();
}
}
Lenny or Jeremy,
Are you still actively building a java integration to QB via XML? If you are, I would like to collaborate with you and any body else in this effort; as I think that is the way to go. My approach is to use JAXB to auto generate the Java object for the XML from the QB DTDs/Schemas and use Lenny’s or Jeremy’s mechanism to pass the XML to QB via QBFC by way of (I guess) JACOB. I would like to use what you have as a starting point. Would you share the source code with me? I tried emailing Lenny; but without any luck.
Thanks!
Tonté
I’ve got these samples to work but having a tough time with complex transactions like creating sales receipts and invoices. Does anyone have samples using this approach with JACOB or anything else Java? TIA – Chris
p.s. email me at chris dot greaves at redtraincom
Does this QB SDK apply to QuickBooks sold in Germany from the company LexWare ?
If not, is there any clue how to export bookings for this LexWare version of QuickBooks ?
Hi all,
Back again after a bit of an absence. The good news is that I’ve completed a full API for accessing QuickBooks seamlessly with Java. With this package, it becomes as easy as in the Visual Studio solutions to interface with QuickBooks.
No need for JACOB heroics (Although a big nod goes to Theoden for pointing a bunch of people in the right direction). You can either build a QBXML object using the API, or use your existing qbXML code directly. The program will handle communications, and return QB’s response as a qbXML string to be parsed in your XML parser of choice.
Here’s a quick example of the code in action. This would be the procedure for adding a new customer:
//**********************************************//
//Create customerAdd request
CustomerAdd newCust = new CustomerAdd();
newCust.Name = “John’s Pizzeria”;
newCust.FirstName = “John”;
newCust.LastName = “Smith”;
newCust.CompanyName = “John’s Pizza”;
newCust.Phone = “555-555-5555”;
//Create billing address for this customer
BillAddress newBilling = new BillAddress();
newBilling.Addr1 = “123 Main St”;
newBilling.Addr2 = “Suite #2”;
newBilling.City = “Beverly Hills”;
newBilling.State = “CA”;
newBilling.PostalCode = “90210”;
//Add it to the customer
newCust.BillAddress = newBilling;
//Since we can add many at the same time, we create a list of new customers to add
ArrayList listOfNewCustomers = new ArrayList();
//Add our new customer to the list
listOfNewCustomers.add(newCust);
QBXML query = new QBXML(); //Initialize Query
query.QBXMLMsgsRq = new QBXMLMsgsRq(); //Create Message Request
query.QBXMLMsgsRq.CustomerAddRq = new CustomerAddRq(); //Initialize customer request.
query.QBXMLMsgsRq.CustomerAddRq.CustomerAdd = listOfNewCustomers; //Add the list of new customer
//Add a requestID. Don’t forget this step!!! QB needs a requestId and onError attribute for all requests.
query.QBXMLMsgsRq.onError = “stopOnError”;
query.QBXMLMsgsRq.CustomerAddRq.requestID = “15”; //Set a request ID.
String asString = query.toString(); //This is a human readable qbXML String.
try {
JQBConnector c = new JQBConnector(“C:/Release/egqb.exe”,”C:\\Test.QBW”); //Initialize Connector and company file.
String ret = c.send(asString); //Send qbXML message to QB.
System.out.println(ret); //Print result.
} catch (JQBException ex) {
ex.printStackTrace();
}
//******************************************************//
Easy huh? This is what the Java community should have received from Intuit in their SDK.
Questions? lenny (at) dragonpg.com
The API can be obtained at : http://www.dragonpg.com/software/quickbooks/
Take a look at the Java Quickbooks API Documentation here: http://www.dragonpg.com/software/quickbooks/doc/
I prefer using QBXMLrp2.dll (qbXML)over the QuickBooks Foundation Classes (QBFC). QBFC have a tendency to get blow out by standard QuickBooks updates, while qbxmlrp2.dll is part of the install so the foundation classes do not have to loaded. On the flip side, using QBFC easier to get the concepts of QuickBooks coding.
@Lenny: Good luck on Intuit doing anything that they do not want to do.
Pingback: Using the QuickBooks SDK via JACOB Java-COM Bridge - Java Tutorial
A Perl transliteration of the original JACOB source code is here:
http://perlmonks.org/?node_id=908940
Thank you for publishing this example. It will help me greatly.
How do you assign attributes to the Message Set Request? I want to translate the second line of the code below to jacob
IMsgSetRequest requestMsgSet = sessionManager.CreateMsgSetRequest(“US”,1,.0);
requestMsgSet.Attributes.OnError = ENRqOnError.roeContinue;
I am writing a java desktop application which will connect to a server and pull various data products. Customers will be charged a ‘per-click’ fee (i.e. Sally at Acme pulls a data report costing $5 anywhere from 1 to several thousand times per day — I want her name, customer ID, product price, date/time, etc. sent to quickbooks each time she does this). So we could potentially have anywhere from 10 to eventually several hundred instances of this application out there.
Anyone have any suggestions as to how I might approach this? I want to use ONLY java so would quickbooks would this api here allow for this integration? What version of quickbooks online would you recommend?
@Marc I’m hardly at expert at this, but If you have QuickBooks Online, then I think you can use Intuit “Data Services”: https://ipp.developer.intuit.com/0010_Intuit_Partner_Platform/0050_Data_Services
Has anyone been able to create a purchase order through Java? I’ve been working on this for a couple of days, but I can’t populate the ORPurchaseOrderLineAddList. I’m assuming I need to append multiples here, but none of the examples I’ve seen goes through this. If anyone can point me in the right direction I’d be grateful.
Thanks!
Super helpful! Thanks so much for posting this. 🙂
Hello! I’m using QB SDK to cycle through transactions and delete them from a particular date onwards. The code works…up to a point. I’m using the ‘TxnType.GetValue’ to get the transaction type, which happens to be a number, and store it as a variable. When I try to use this value, in TxnDelType.SetValue, it does not work. It only works if I use the transaction type as the enumerated value eg tdlInvoice, etc. How can I convert the transaction type number to the enumerated value.
This is an old thread but hopefully I can get an answer from here.
I ran the example to retrieve all Vendors and works very well, thanks for that! The insert example provided by Sam in 2008 might also work, haven’t tried it yet. I’m wondering if there is a way to fetch for a single Vendor record and also a way to edit it. Also, I see that “AppendVendorAddRq” is used for the Vendor scenarios but what about for other objects? Is there a site with documentation?
Thanks for any help!
I try to run this program but it is not working in QB SDK13. Any one tell me how to run in eclipse with SDK13.
Thanks for Reply.
Has anyone tried using JACOB for IBM PCOMM emulator?
@sam, I have some source code available if you’d like to look it over. I am using QBSDK 13 with QB Pro 2013 Request Processor in JDK 1.7. Let me know your email and I’ll send it to you. Be sure that the request process is up and running, your application has received permission from the company file administrator, and the SDK is installed.
@Checo, (if you still check this) Did you ever figure out how to add the “OnError” attribute in java? If so, I’d really like to know. The work-around is having a different session manager and message set for each request (as I’ve had to resort to this because of time constraints) but I’d really like a more elegant solutions by adding the “OnError” attribute. This one issue is annoying!
Hello Jeff, did you manage to add a purchase order to Quickbooks?
Does anyone know how to add a purchase order to Quicbooks using QuickBooks SDK via JACOB Java-COM Bridge. I have spent the whole week working on this. Your help will be much appreciated.
We are getting error while connecting with the QuickBooks Enterprise Solutions 15.0(desktop version) using the Jacob library.
The code we are using is :
import com.jacob.com.*;
import com.jacob.activeX.*;
public class Foo {
public static void main(String[] args) {
System.out.println(“Hello world!”);
// QBFC constants looked up using the object browser
Variant ctLocalQDB = new Variant(1);
Variant omDontCare = new Variant(2);
// major and minor version of qbXML used to talk to QuickBooks
Variant qbXMLMajor = new Variant(6);
Variant qbXMLMinor = new Variant(0);
// location of the company file to access
String qbFile = “C:\\Users\\Public\\Documents\\Intuit\\QuickBooks\\Sample Company Files\\QuickBooks Enterprise Solutions 14.0\\Oceanic Test.qbw”;
// connect to QuickBooks
Dispatch qbsm = new Dispatch(“QBFC13.QBSessionManager”);
Dispatch.call(qbsm, “OpenConnection2”, “”, “My Sample App”, ctLocalQDB);
Dispatch.call(qbsm, “BeginSession”, qbFile, omDontCare);
// build and execute a request to obtain all vendors
Dispatch msgSet = Dispatch.call(qbsm, “CreateMsgSetRequest”, “US”, qbXMLMajor, qbXMLMinor).toDispatch();
Dispatch.call(msgSet, “AppendVendorQueryRq”);
Dispatch resSet = Dispatch.call(qbsm, “DoRequests”, msgSet).toDispatch();
Dispatch resList = Dispatch.get(resSet, “ResponseList”).toDispatch();
int count = Dispatch.get(resList, “Count”).getInt();
for (int i = 0; i < count; i++) {
Dispatch res = Dispatch.call(resList, "GetAt", new Variant(i)).toDispatch();
// blindly assume that we have a vendor response
Dispatch vendList = Dispatch.get(res, "Detail").toDispatch();
int vcount = Dispatch.get(vendList, "Count").getInt();
for (int j = 0; j < vcount; j++) {
Dispatch vend = Dispatch.call(vendList, "GetAt", new Variant(j)).toDispatch();
Dispatch dname = Dispatch.get(vend, "Name").toDispatch();
String name = Dispatch.call(dname, "GetValue").getString();
System.out.println("Vendor: " + name);
}
}
// close the QuickBooks connection
Dispatch.call(qbsm, "EndSession");
Dispatch.call(qbsm, "CloseConnection");
System.out.println("Goodbye world!");
}
}
We are getting the following error:
Hello world!
Exception in thread "main" com.jacob.com.ComFailException: Can't co-create object
at com.jacob.com.Dispatch.createInstanceNative(Native Method)
at com.jacob.com.Dispatch.(Dispatch.java:99)
at Foo.main(Foo.java:16)
Line 16 – Dispatch qbsm = new Dispatch(“QBFC13.QBSessionManager”);
We are using Windows server 64 bit. We have checked over web and they are saying to add dll file(jacob-1.18-M2-x64.dll) that is given in the dowloaded Jacob. We tried all the things that are available but not able to resolve the error.
Please suggest where we are doing wrong.
Thanks,
Astrea IT Services
Hello, I know this thread is old but I think it’s going to be very helpful for me. I have a java desktop application I will like to send transactions from it to quickbooks. I will appreciate tutorials and documentation for me to go through.
Great job all!
As the years go by I continue to be surprised by the traffic this blog post continues to receive. I wrote this over 7 years ago, but I’m glad it still seems to be helping people out!
HI guys!!!!!
I have a task about quickbooks on how to add, deduct item inventory and add a chart of accounts. Can you give me links where I can study do finish this task….. Any help is Highly Appreciated..
Hello,
We are getting the following error:
Exception in thread “main” com.jacob.com.ComFailException: Can’t co-create object
at com.jacob.com.Dispatch.createInstanceNative(Native Method)
at com.jacob.com.Dispatch.(Dispatch.java:99)
I have tried everything. Placing the dll in system32 and using regsvr32 to register the dll but with no success. If anyone was able to solve this then kindly suggest any mechanism to counter this. Any help would be greaty appreciated.
Thanks
Thanks,
Pavan
You should use JDK x32 bit Pavan.
Hi!
I’m trying to do an insert on QB based on the code above.
I get this error :
Exception in thread “main” com.jacob.com.ComFailException: Invoke of: DoRequests
Source: QBFC7.QBSessionManager.1
Description: Missing ‘onError’ attribute.
My code is (the one from sam above):
Dispatch setMsg = Dispatch.call(msgSet, “AppendVendorAddRq”).toDispatch();
Dispatch name = Dispatch.get(setMsg, “Name”).toDispatch();
Dispatch.call(name, “setValue”, “testing”);
Dispatch cName = Dispatch.get(setMsg, “CompanyName”).toDispatch();
Dispatch.call(cName, “setValue”, “testing company”);
Dispatch address = Dispatch.get(setMsg, “VendorAddress”).toDispatch();
Dispatch addrline = Dispatch.get(address, “Addr1”).toDispatch();
Dispatch.call(addrline, “setValue”, “address”);
Dispatch addrCity = Dispatch.get(address, “City”).toDispatch();
Dispatch.call(addrCity, “setValue”, “City”);
Dispatch addrState = Dispatch.get(address, “State”).toDispatch();
Dispatch.call(addrState, “setValue”, “State”);
Dispatch addrZip = Dispatch.get(address, “PostalCode”).toDispatch();
Dispatch.call(addrZip, “setValue”, “59236”);
resSet = Dispatch.call(qbsm, “DoRequests”, msgSet).toDispatch();
resList = Dispatch.get(resSet, “ResponseList”).toDispatch();
error appears at this line : resSet = Dispatch.call(qbsm, “DoRequests”, msgSet).toDispatch();
Any help would be amazing 🙂
Exception in thread “main” java.lang.UnsatisfiedLinkError: no jacob-1.18-x64 in java.library.path
How to resolve this issue.
Brindha – This solution sucks, but I had to put the jacob-1.18-x86.dll in the jdk\bin folder.
Note: I wasn’t able to even get the UnstatisfiedLinkError using 64 bit dll. I kept getting “Can’t co-create object”, but got past it by switching to 32 bit JVM.
Does anyone know if it’s possible to use 64 bit JVM? Everywhere I am seeing, everyone says you must use 32 bit JVM, but if that’s the case then why do they provide 64 bit dll?
Hi,
I am working on the above POC, but getting com.jacob.com.ComFailException: Can’t co-create. I am able to call other COMs like Outlook.Application or Onenote.Application.
I’m using Quickbooks Desktop 2020 version with Jacob 1.19.
So is there any concrete solution for this?
Thank you.
Hey, just want to report that I have been using this solution for a couple years now and it works as well as any QB integration. A few tips:
– You have to use 32 bit version of Java (i.e. Java 8 or less)
– Find the xsd files in the QBSDK files and use the jaxb command line tool to convert the xml schema into classes. I bundled all the classes into a jar, but you could just use the ones you need too.
– Use the XML Validator and qbXMLTest+ tools that come with the qbSDK
– Refer to the programmers guide that comes with the qbSDK
The basic code (which I have wrapped in a DAO) looks like this:
———————————————————————
//Open a Connection
Dispatch requestProc = new Dispatch(“QBXMLRP2.RequestProcessor”); //notice this is different than the example on this page.
Dispatch.call(requestProc, “OpenConnection2”, “”, “Your App Name Here”, 1);
try {
String xml = …Your XML Request…; //hint:use jaxb
//Begin a session
private Variant ticket = Dispatch.call(requestProc, “BeginSession”, “…path to your QB file here…”, 2);
String response = Dispatch.call(requestProc, “ProcessRequest”, ticket, xml).toString();
//…use jaxb to parse string back to object and handle object.
//…check the status severity and status message – throw error if needed
} finally {
//End Session
if(requestProc != null && ticket != null)
Dispatch.call(requestProc, “EndSession”, ticket);
}
//After all processing is done, Close connection
if(requestProc != null)
Dispatch.call(requestProc, “CloseConnection”);
—————————————————————————————
Lastly, here is a sample request to help you with flow…
—————————————————————————————
800009F5-1511193547
My Test Company
2019-10-15
0-1
My Test Company
3644 West Apple Rd
Big Rock
IL
84870
9876
80000009-1511193457
JAM
{63bd4065-94af-4b5d-ba1c-a81f889e4199}
TxnID
TimeCreated
ExternalGUID
RefNumber
Sorry, not trying to spam here, but it looks like I needed to escape some characters, so re-posting with escapes.
Hey, just want to report that I have been using this solution for a couple years now and it works as well as any QB integration. A few tips:
– You have to use 32 bit version of Java (i.e. Java 8 or less)
– Find the xsd files in the QBSDK files and use the jaxb command line tool to convert the xml schema into classes. I bundled all the classes into a jar, but you could just use the ones you need too.
– Use the XML Validator and qbXMLTest+ tools that come with the qbSDK
– Refer to the programmers guide that comes with the qbSDK
The basic code (which I have wrapped in a DAO) looks like this:
———————————————————————
//Open a Connection
Dispatch requestProc = new Dispatch(“QBXMLRP2.RequestProcessor”); //notice this is different than the example on this page.
Dispatch.call(requestProc, “OpenConnection2”, “”, “Your App Name Here”, 1);
try {
String xml = …Your XML Request…; //hint:use jaxb
//Begin a session
private Variant ticket = Dispatch.call(requestProc, “BeginSession”, “…path to your QB file here…”, 2);
String response = Dispatch.call(requestProc, “ProcessRequest”, ticket, xml).toString();
//…use jaxb to parse string back to object and handle object.
//…check the status severity and status message – throw error if needed
} finally {
//End Session
if(requestProc != null && ticket != null)
Dispatch.call(requestProc, “EndSession”, ticket);
}
//After all processing is done, Close connection
if(requestProc != null)
Dispatch.call(requestProc, “CloseConnection”);
—————————————————————————————
Lastly, here is a sample request to help you with flow…
—————————————————————————————
<?xml version=”1.0″ encoding=”US-ASCII” standalone=”no”?>
<?qbxml version=”13.0″?>
<QBXML>
<QBXMLMsgsRq onError=”stopOnError”>
<SalesOrderAddRq requestID=”2″>
<SalesOrderAdd>
<CustomerRef>
<ListID>800009F5-1511193547</ListID>
<FullName>My Test Company</FullName>
</CustomerRef>
<TxnDate>2019-10-15</TxnDate>
<RefNumber>0-1</RefNumber>
<ShipAddress>
<Addr1>My Test Company</Addr1>
<Addr2>3644 West Apple Rd</Addr2>
<City>Big Rock</City>
<State>IL</State>
<PostalCode>84870</PostalCode>
</ShipAddress>
<PONumber>9876</PONumber>
<SalesRepRef>
<ListID>80000009-1511193457</ListID>
<FullName>JAM</FullName>
</SalesRepRef>
<ExternalGUID>{63bd4065-94af-4b5d-ba1c-a81f889e4199}</ExternalGUID>
</SalesOrderAdd>
<IncludeRetElement>TxnID</IncludeRetElement>
<IncludeRetElement>TimeCreated</IncludeRetElement>
<IncludeRetElement>ExternalGUID</IncludeRetElement>
<IncludeRetElement>RefNumber</IncludeRetElement>
</SalesOrderAddRq>
</QBXMLMsgsRq>
</QBXML>
Is there any way to do this using the x64 bit java?
@Patrick,
Yes, you have to create a DLL surrogate in the registry.
I posted a how to just because I had so many problems, to help out.
https://youtu.be/yenpA-6Q3gs
There is a link to the github project so you can look at the code.
Take care.
Hi Jose thank you for the article. I was able to develop the application in java but i have a challenge deploying the same as a service. would you happen to have any ideas?