bare-knuckle web development

51
Bare-knuckle web development Odessa Johannes Brodwall, Chief scientist Exilesoft Global

Upload: dot

Post on 04-Feb-2016

41 views

Category:

Documents


0 download

DESCRIPTION

Bare-knuckle web development. Odessa Johannes Brodwall, Chief scientist Exilesoft Global. Bare-knuckle philosophy Demonstration of bare-knuckle web in Java Further directions. Part I:. The bare-knuckle philosophy. High impact/low ceremony Framework light Test-driven. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Bare-knuckle web development

Bare-knuckle web development

OdessaJohannes Brodwall, Chief scientist

Exilesoft Global

Page 2: Bare-knuckle web development

• Bare-knuckle philosophy• Demonstration of bare-

knuckle web in Java• Further directions

Page 3: Bare-knuckle web development

Part I:

Page 4: Bare-knuckle web development

The bare-knuckle philosophy

Page 5: Bare-knuckle web development

• High impact/low ceremony• Framework light

• Test-driven

Page 6: Bare-knuckle web development

High impact with low ceremony

Page 7: Bare-knuckle web development

Java web: Servlets, WebDriver, Jetty,

Mockito

Page 8: Bare-knuckle web development

Java SOAP: JOOX, HttpURLConnection

Page 9: Bare-knuckle web development

.NET web prototype: WebDriver + HttpListener

Page 10: Bare-knuckle web development

.NET web work-in-progress:

WebDriver + HttpSelfHostServer

Page 11: Bare-knuckle web development

Light on framework

Page 12: Bare-knuckle web development

Frameworks solve 80% of the job…

Page 13: Bare-knuckle web development

… and makes the rest 10 times as hard

Page 14: Bare-knuckle web development

“Why did Hibernate suddenly slow down?”

Page 15: Bare-knuckle web development

“How do I implement a custom SOAP header

with JAX-WS?”

Page 16: Bare-knuckle web development

“How to do X with Spring”

Page 17: Bare-knuckle web development

@AutoWire + package scan with 100s of beans

Page 18: Bare-knuckle web development

Test-driven

Page 19: Bare-knuckle web development

No more architecture than what’s needed

Page 20: Bare-knuckle web development

Fast feedback cycle – also in the future

Page 21: Bare-knuckle web development

Part II:

Page 22: Bare-knuckle web development

Demo: Phonebook web app

Page 23: Bare-knuckle web development

Test driving

Page 24: Bare-knuckle web development

WebDriver browser = createWebDriver();

browser.get(url);browser.findElement(By.linkText("Add contact")).click();

browser.findEleme(By.name("fullName")).sendKeys("Vader");browser.findEleme(By.name("phoneNumber")).sendKeys("27");browser.findEleme(By.name("saveContact")).click();

browser.findElement(By.linkText("Find contact")).click();browser.findElem(By.name("nameQuery")).sendKeys("vader");browser.findElement(By.name("nameQuery")).submit();

assertThat(browser.findElem(By.id("contacts")).getText()) .contains("555-33274-7827");

Page 25: Bare-knuckle web development

Server server = new Server(0);server.setHandler( new WebAppContext("src/main/webapp", "/contacts"));server.start();

int port = server.getConnectors()[0].getLocalPort();String url = "http://localhost:" + port + "/contacts";

Page 26: Bare-knuckle web development

<web-app version="2.5“>

<servlet> <servlet-name>contactServlet</servlet-name> <servlet-class> com.exilesoft.bareknuckleweb.ContactServlet </servlet-class></servlet>

<servlet-mapping> <servlet-name>contactServlet</servlet-name> <url-pattern>contact/*</url-pattern></servlet-mapping>

</web-app>

Page 27: Bare-knuckle web development

public class ContactServlet extends HttpServlet {}

Page 28: Bare-knuckle web development

@Testpublic void shouldShowAddForm() throws Exception { ContactServlet servlet = new ContactServlet(); HttpServletRequest req = mock(HttpServletRequest.class); HttpServletResponse resp = mock(HttpServletResponse.class); StringWriter html = new StringWriter();

when(resp.getWriter()).thenReturn(new PrintWriter(html)); when(req.getPathInfo()).thenReturn("/create.html");

servlet.doGet(req, resp);

verify(resp).setContentType("text/html"); assertThat(html.toString()) .contains("<form method='post'") .contains("<input type='text' name='fullName'") .contains("<input type='text' name='phoneNumber'") .contains("<input type='submit' name='createContact'");}

Page 29: Bare-knuckle web development

Refactoring

Page 30: Bare-knuckle web development

Part III:

Page 31: Bare-knuckle web development

Further directorions

Page 32: Bare-knuckle web development

Norwegian agricultural

authority

Page 33: Bare-knuckle web development

Java web application with an MVC architecture

Page 34: Bare-knuckle web development

Controllers:• Create a view

• Retrieve model from repo• Set model on view

• Render view

Page 35: Bare-knuckle web development

View example:

Page 36: Bare-knuckle web development

@Overridepublic void render(HttpServletResponse resp) throws IOException { Match document = $("html", head(), $("img").attr("src", "/sms-varsel/Sparebank1.jpg"), $("h1", "Internet bank simulator"), $("form").attr("method", "post").append( hiddenField(this.bankNum, "bankNum"), hiddenField(this.customerId, "customerId"), $("h2", "Set Mobile Phone Number"), phoneNumberField(this.phoneNumber), $("h2", "Account numbers"), accountNumbersField(this.accountNumbers), $("h2", "Payment account"), paymentAccountField(this.defaultAccount), $("h2", "Save changes"), $("div", $("input").attr("type", "submit").attr("value", "Store")).attr("name", "update"))); resp.setContentType("text/html"); resp.setCharacterEncoding("UTF-8"); resp.getWriter().write(document.toString());}

Page 37: Bare-knuckle web development

Match document = $("html", head(), $("img").attr("src", "/logo.jpg"), $("h1", “Page name"), $("form").attr("method", "post").append( hiddenField(this.bankNum, "bankNum"), hiddenField(this.customerId, "customerId"), $("h2", "Save changes"), $("div", $("input").attr("type", "submit") .attr("value", "Store")) .attr("name", "update")));

Page 38: Bare-knuckle web development

Norwegian Power Transmission

System Operator

Page 39: Bare-knuckle web development

Universal repository

Universal service

Commands and Queries

One domain model

Page 40: Bare-knuckle web development

No Spring – 100 KLOC

Page 41: Bare-knuckle web development

Single-jar deployment• Includes scripts

• Includes Jetty

Page 42: Bare-knuckle web development

public class StatnettWebServer { private final org.eclipse.jetty.server.Server server; public ContactWebServer(int port) { server = new Server(port); server.setHandler(new WebAppContext(“…", "/statnett")); }

void start() throws Exception { server.start(); }

String getUrl() { int port = server.getConnectors()[0].getLocalPort(); return "http://localhost:" + port + "/contacts"; }

public static void main(String[] args) throws Exception { StatnettWebServer server = new StatnettWebServer(10080); server.start(); System.out.println(server.getUrl()); }}

Page 43: Bare-knuckle web development

SpareBank1

Page 44: Bare-knuckle web development

10 web service clients

Page 45: Bare-knuckle web development

HttpURLConnection

JOOX

Page 46: Bare-knuckle web development

@Overridepublic String getCountryByIp(String ipAddress) throws Exception { Document soapRequest = soapElement("S:Envelope", $("S:Body", wsxElement("wsx:GetGeoIP", $("wsx:IPAddress", ipAddress)))); Document soapResponse endpoint.postRequest(getSOAPAction(), soapRequest); return $(soapResponse).xpath("/Envelope/Body/*") .xpath("GetGeoIPResult/CountryName").text();}

Page 47: Bare-knuckle web development

public Document postRequest(String soapAction, Document soapRequest) { HttpURLConnection conn = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.setDoOutput(true); connection.addRequestProperty("SOAPAction", soapAction); connection.addRequestProperty("Content-Type", "text/xml"); $(soapRequest).write(connection.getOutputStream());

int responseCode = connection.getResponseCode(); if (isErrorResponse(responseCode)) { String response = toString(connection.getErrorStream()); String responseContentType = connection.getContentType(); if (responseContentType.startsWith("text/xml")) { return response; } throw new ServiceCommunicationException( "On POST to " + url + ": " + responseCode + " " + connection.getResponseMessage() + ": " + response); } return $(connection.getInputStream()).document();d}

Page 48: Bare-knuckle web development

Conclusion:

Page 49: Bare-knuckle web development

YAGNI

Page 50: Bare-knuckle web development

Test-driven development

High investment in tests

Low investment in frameworks

Page 51: Bare-knuckle web development

Thank [email protected]

http://johannesbrodwall.com

http://exilesoft.com

http://twitter.com/jhannes