Diese drei Zeilen machst du z.B. in beiden Methoden und können daher in eine private Hilfsfunktion ausgelagert werden, der du nur die URL als String-Parameter übergibst.
Weiters vl keine statischen Funktionen, sondern ein Object erzeugen bei dem du am Konstruktor username, passwort und domain einmal angibst und dann bei den Methoden nicht mehr.
Danke, das erstellen des Webtargets, würde ich sogar in eine Klasse haben wollen (static?)
Ich werde noch weitere Klasse erstellen in welchen dann die Kategorien, Bestellungen etc verarbeitet werden, diese brauchen ja auch alle eine Verbindung zur API, da bietet sich eine Klasse „APiConnection“ an oder? In dieser dann eine Methode static getWebtarget(domain, apiName, apiPasswort)?
ICh dachte eher an so etwas (Achtung nur pseudo code)
public ShopwareProductServiceHelper {
private String domain;
private String user;
private String pw;
public ShopwareProductServiceHelper (domain, user, pw) {
...
}
private ResteasyWebTarget buildWebTarget(String path) {
ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget webTarget = client.target(domain + "/api/articles/");
webTarget.register(new BasicAuthentication(user, password));
return webTarget;
}
public <T> T get(String path, Class<T> responseClass) {
var webTarget = buildWebTarget(path)
T result = response.readEntity(responseClass);
return result;
}
public <T,R> R post(String path, T bodyContent, Class<R> responseClass) {
var webTarget = buildWebTarget(path)
Response response = webTarget.request().post(Entity.entity(bodyContent, "application/json"));
R result = response.readEntity(responseClass);
return result;
}
public class ShopwareProductService {
private ShopwareProductServiceHelper communiction = .....;
public getProduct(String productSKU) {
communiction.get("/api/articles/" + productSKU + "?useNumberAsId=true",ShopwareProduct.class);
}
public createProduct(... any parameter you need to create a product) {
ShopwareProduct product = new ShopwareProduct();
product.setName("Blabla");
product.setTax("19");
product.setSupplier("Nike");
product.setActive(true);
/*
* Prices
*/
List<Prices> priceList = new ArrayList<>();
Prices prices = new Prices();
prices.setCustomerGroupKey("EK");
prices.setPrice(99.99);
priceList.add(prices);
MainDetail mainDetail = new MainDetail();
mainDetail.setNumber("SKUJJJ");
mainDetail.setEan("123235423423");
mainDetail.setSupplierNumber("q6511x");
mainDetail.setActive(true);
mainDetail.setPrices(priceList);
product.setMainDetail(mainDetail);
communication.post(/api/articles/,product,String.class);
}
}
aber auch hier würde ich auf jegliches static verzichten. Da ich Resteasy nicht kenne weis ich natürlich nicht welche einschränkungen die Generischen Parameter R und T haben müssten. Also z.B
näheres bezüglich generische Parameter findest du in dem Link
der Vorteil von diesem generischen Zeug ist, dass du get und post für verschiedene Object-Klassen wieder verwenden kannst und nicht jedes mal eine neue post-Methode schreiben musst.
Die Verwendung siehst du eh in der createProduct-Methode oben
Ich finde das auf jeden Fall lesbar. Eventuell würde ich einzelne Teile in private Klassen auslagern. Wenn eine Klasse allerdings Helper im Namen trägt, klingt das für mich schon “nicht optimal”. Nach IOSP könnte man z.B. die Target-Url bzw sogar den Aufbau des Requests in eine Methode kapseln.
Wie du aber in deinem Bsp siehst, hast du jedesmal ziemlcih viel Code der in jedem aufruf gleich ist. z.B.
new ResteasyClientBuilder().build()
register(BasicAuth)
target(domain nur der pfad dahinter ändert sich
deswegen wollte ich ihm vorschlagen, dies noch einmal wegzukappseln
Ja der Name ist definitiv unglücklich gewählt, weil dern Name vl doch eher „ShopwareProductServiceCommunication“ sein sollte.
Wahrscheinlich ähnlich wie @AmunRa in seiner Helper-Klasse nur als private Methoden. Ich würde das, was accept() zurückgibt in der Methode zurückgeben.
Soweit so gut, danke euch beiden! Nun ist es etwas lesbarer, aber so ganz auf dem Holzweg war ich nicht oder? So ein Design erarbeitet man vielleicht auch öfter mal im Team oder? (Wenn man ein Team hat ;P)
Eins noch, seit ich die genersischen Methoden nutze, bekomme ich folgende Meldung
Can not deserialize instance of product.Data out of START_ARRAY token
und zwar hier
public <T> T get(String path, Class<T> responseClass) {
ResteasyWebTarget webTarget = buildWebTarget(path);
Response response = webTarget.request().get();
//System.out.println(response.readEntity(String.class)); //Ausgabe ist korrekt
T result = response.readEntity(responseClass); //HIER EXCEPTION
return result;
}
Habe mit RestEasy in letzter Zeit wenig gemacht, aber dein Modell muss zu der Antwort passen. Schau dir doch einfach mal den String an, ob er strukturell passt.
Generell ist ein String mit selbst parsen allerdings häufig stabiler, was externe APIs angeht.