Wiki
Clone wikimyob-api / Home
Welcome
This API provides a java interface to interact with the MYOB API.
Main characteristics
- Supports desktop and cloud versions of MYOB
- All entity classes have been translated to java from the 'Contracts' package of the .NET c# SDK provided by MYOB.
- Two transport classes have been implemented, one using the Apache Http Client library, the other one using plain Java SE (HttpUrlConnection).
- Google Gson is used for java to json serialization.
- API supports CDI 1.2 and uses Weld-SE in SE environments.
- Apache 2 Licensed
Support by donation at http://irc.anahata.uno
Loving developers: http://anahata.net.au
Maven
The artifacts are deployed to Anahata's maven repository
#!xml <repositories> <repository> <id>anahata</id> <name>Anahata Public Repo</name> <url>http://artifactory.anahata-it.com.au/artifactory/anahata-public/</url> </repository> </repositories> <dependencies> <dependency> <groupId>com.anahata</groupId> <artifactId>myob-api</artifactId> <version>1.5.4</version> </dependency> </dependencies>
Java SE Quickstart
OAuth Log in from a standalone desktop javafx application to get access and refresh tokens and list all company files of the logged in user
#!java JavaFXOAuthAuthenticatorApp.loginAndGetToken(new MyobPlugin("qumsp9e1b8ynw9zhbsbt53dx", "Sj3kswJqB521WmbnqG5XuBWk", "http://localhost")); OAuthAccessToken token = JavaFXOAuthAuthenticatorApp.ret; CompanyFileService.findAll(token);
Retrieve all suppliers of a cloud data file. If the API detects that a token refresh is needed, allow storing the new access and refresh token
#!java SupplierService cfs = new SupplierService(); cfs.setEndPointProvider(new MyobEndPointProvider() { @Override public MyobEndPoint getEndPoint() { OAuthAccessToken token = //read token from database; return new MyobEndPoint(MyobEndPoint.CLOUD_ENDPOINT + "b2c48941-7bfb-4f7c-9356-309127f15221", new DataFileCredentials(), token); } @Override public void oauthTokenRefreshed(MyobEndPoint locator) { //store access and refresh token here } }); return cfs.findAll();
CDI provided Endpoints
The API can work with CDI (in both SE and EE environments) to provide data file url and credentials without having to configure each an MYOB service instances.
CDI based EndPoint provider supplying EndPoint (Data file locator + OAuth credentials + data file credentials). Use case of one data file and one logon for the entire application. You can Use @RequestScoped rather than @Singleton in a multi datafile, multi user scenario.
#!java /** * Singleton EJB to store supply myob endpoint details and store access and refresh token whenever it gets refreshed. * * @author pablo */ @ConcurrencyManagement(CONTAINER) @Singleton @Slf4j @Lock(LockType.WRITE) public class MyobEndPointProviderServiceImpl implements MyobEndPointProviderService { @Inject @Yam private EntityManager em; @Inject private DomainConfigServiceImpl dcs; private MyobEndPoint endPoint; @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public MyobEndPoint getEndPoint() { if (endPoint != null) { log.debug("Returning existing singleton endPoint instance {}", endPoint); return endPoint; } DomainConfig dc = dcs.getDomainConfigLocal(); endPoint = new MyobEndPoint(dc.getMyobEndPointUrl()); endPoint.getCredentials().setUser(dc.getMyobCompanyFileUser()); endPoint.getCredentials().setPassword(dc.getMyobCompanyFilePassword()); if (dc.getMyobKey() != null) { MyobPlugin mp = new MyobPlugin(dc.getMyobKey(), dc.getMyobSecret(), dc.getMyobRedirectUrl()); OAuthAccessToken oaat = new OAuthAccessToken(mp, dc.getMyobAccessToken(), dc.getMyobRefreshToken(), dc.getMyobAccessTokenDate(), dc.getMyobAccessTokenExpiresIn()); endPoint.setOauthAccessToken(oaat); } log.debug("Returning newly created singleton endPoint instance {}", endPoint); return endPoint; } //if the token is refreshed, we want to make sure the storage operation succeeds regardless of the transactional context @Override @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void oauthTokenRefreshed(MyobEndPoint endPoint) { log.debug("OauthTokenRefreshed, storing on DB"); DomainConfig dc = dcs.getDomainConfigLocal(); dc.setMyobAccessToken(endPoint.getOauthAccessToken().getAccessToken()); dc.setMyobRefreshToken(endPoint.getOauthAccessToken().getRefreshToken()); dc.setMyobAccessTokenDate(endPoint.getOauthAccessToken().getCreatedOn()); dc.setMyobAccessTokenExpiresIn(endPoint.getOauthAccessToken().getExpiresIn()); em.merge(dc); em.flush(); log.debug("Updating singleton endpoint instance"); //update singleton instance getEndPoint().getOauthAccessToken().setAccessToken(endPoint.getOauthAccessToken().getAccessToken()); getEndPoint().getOauthAccessToken().setCreatedOn(endPoint.getOauthAccessToken().getCreatedOn()); getEndPoint().getOauthAccessToken().setExpiresIn(endPoint.getOauthAccessToken().getExpiresIn()); getEndPoint().getOauthAccessToken().setRefreshToken(endPoint.getOauthAccessToken().getRefreshToken()); } }
Then on a EJB or any other CDI enabled object
#!java /** * Performs persistence operations on customer such as search. * * @author pablo */ @Stateless @LocalBean public class SomeApplicationService { /** Myob Customer Service with CDI configured endpoint and credentials **/ @Inject private CustomerService myobCustomerService; }
Adding additional services or convenience methods to the API
While all MYOB entity classes exist in the API, only the services we have needed have been implemented. Implementing a service which has not yet been written is as simple as implementing a simple Service class and its corresponding Page object. Feel free to create new services and add a pull request.
First AccountService.java
#!java /** * Account Service * * @author pablo */ public class AccountService extends AbstractEntityMyobService<AccountPage, Account> { public AccountService() { super("GeneralLedger/Account", AccountPage.class, Account.class); } //Your handy methods public Account findByDisplayID(String displayID) { List<Account> accounts = super.findAll(); for (Account account : accounts) { if (Objects.equal(account.getDisplayID(), displayID)) { return account; } } return null; } }
#!java @Data public class AccountPage extends EntityPage<Account>{ public List<Account> Items; }
Updated