1 / 60

Effective Enterprise Java Johannes Brodwall Chief scientist, Steria Norway

Effective Enterprise Java Johannes Brodwall Chief scientist, Steria Norway.  www.steria.no. What I have prepared. In order to design, develop or maintain an enterprise information system in Java (web, database) As a senior developer

hang
Download Presentation

Effective Enterprise Java Johannes Brodwall Chief scientist, Steria Norway

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Effective Enterprise Java Johannes Brodwall Chief scientist, Steria Norway www.steria.no

  2. What I have prepared • In order to design, develop or maintain an enterprise information system in Java (web, database) • As a senior developer • I want to learn how to approach important aspects of my application

  3. My responsibity as an instructor • To give the best answer I can to the problems you have • To be honest when I’m unsure about a question • To listen to your wishes for topics throughout the tutorial

  4. Konfidensiell - Navn på presentasjon.ppt Your responsibilties as participants • To ask your most pressing questions • To participate actively • To let me know if we spend too much time on a topic • To challenge me when you think I’m wrong

  5. Contents • Architecture • Communication • Processing • State management • Presentation • Security

  6. Top take-aways • Development • Invest in unit and integration level tests • Architecture • Isolate each processing event and abort if you can’t complete • Communication • Fowler's First Law of Distributed Object Design: Don’t distribute your objects • Processing • Prefer local transactions to distributed ones • State management • Understand the underlying relational model before using an ORM tool • Presentation • Design your system from the outside in • Security • Treat all data from outside as tainted

  7. Agenda • Architectural overview of enterprise applications • Sections (a la carte) • Preparated materials • Without prepared materials • Suggestions from you • Things I don’t know • Breaks at ???

  8. Section menu a la carte • Prepared materials • Integration testing • Unit testing enterprise applications • Persistence (ORM basics, ORM advanced) • Scalability • Distributed applications • Security • Client options • Without prepared materials • Continuous Deployment • Putting transactions, state and processing into context • A practical approach to system design • Machine-enabled interfaces • Suggestions from you • Things I don’t know

  9. Participant stories • In order to <solve a problem in my job> • As a <job title> • I want to learn about <subject>

  10. Disclaimer! Code is presented as stand-alone as possible – in real systems, refactor to remove duplication

  11. The world has changed

  12. Enterprise Java Architecture 2009 • Every processing is triggered by an event • Usually: Timed trigger, incoming http request, incoming message • All triggers can be forged • Every processing event should be isolated • Retrieve all data as you need it • Update all data at an end • Do optimistic locking • All objects are short-lived or immortal and stateless • Unexpected errors should rollback everything, log and abort • Any, oh, EJBs are more trouble than they’re worth

  13. 10 000 ft architecture

  14. Clients Internet/intranet Perimeter Application Information

  15. 3 000 ft http architecture

  16. What you need to care about Identify user Interpret request Render response Yourapplication Identify action and flow Isolate processing Read and persist information

  17. 3 000 ft thick client architecture

  18. What you need to care about Manage events Present data Server module Identify user API Wire protocol Server module Identify action and flow Read and persist information

  19. Scalability What are you bottlenecks?

  20. Scalability: Only two solutions, one problem • Solution #1: Add more identical nodes • Solution #2: Cache at some level • Problem: Data out of sync

  21. Bottlenecks #1: Make one app server performant • Poor SQL performance – trace and optimize SQL • Garbage collection screw-up – check with a memory profiler • Rendering similar pages repeatedly – page caching • Stateful pages get in the way of caching – make saner URLs • User-info gets in the way of caching – render with JavaScript and cookies • Offload static content • Increase hardware

  22. Bottleneck #2: Horizontal app server scaling • More seldom than you’re led to think! (e.g. stackoverflow.com) • In principle simple: mod_whatever in Apache frontend • Problems: Session • Solutions • No session (authentication in perimeter) • Sticky sessions • Distributed sessions • Cookie-based sessions

  23. Bottleneck #3: Database scalability • Two basic solutions • Expensive, poorly-understood distributed RDBMSs • Caching • Caching: • In application server • In read-only database mirrors • Seperate read and write-requests to different app servers (on HTTP verbs or URLs) • Tradeoff: How often should users see stale data? Should they ever see own stale data?

  24. Integration testing web applications • Live demo

  25. Integration testing web applications @Test publicvoidshouldFindSavedPeople() throws Exception { org.mortbay.jetty.Server server = neworg.mortbay.jetty.Server(0); server.addHandler(newWebAppContext("src/main/webapp", "/")); server.start(); String rootUrl = "http://localhost:" + server.getConnectors()[0].getLocalPort() + "/"; org.openqa.selenium.WebDriverbrowser = neworg.openqa.selenium.htmlunit.HtmlUnitDriver(); browser.get(rootUrl); browser.findElement(By.linkText("Create a new person")).click(); browser.findElement(By.name("full_name")).sendKeys("Johannes Brodwall"); browser.findElement(By.name("create")).click(); browser.findElement(By.name("name_query")).sendKeys("johannes"); browser.findElement(By.name("search")).click(); browser.findElement(By.xpath(".//*[text() = 'Johannes Brodwall']")); }

  26. Unit testing enterprise applications • Live demo: Servlet testing • Live demo: Hibernate testing

  27. Unit testing servlets with Mockito @Test publicvoid shouldSearchForPerson() throws Exception { HttpServletRequest req = org.mockito.Mockito.mock(HttpServletRequest.class); HttpServletResponse resp = mock(HttpServletResponse.class); StringWriter pageSource = new StringWriter(); when(resp.getWriter()).thenReturn(new PrintWriter(pageSource)); when(req.getMethod()).thenReturn("GET"); when(req.getPathInfo()).thenReturn("/find.html"); when(req.getParameter("name_query")).thenReturn("foobar"); PersonDao personDao = mock(PersonDao.class); PersonServlet servlet = new PersonServlet(); servlet.setPersonDao(personDao); servlet.service(req, resp); verify(personDao).find("foobar"); DocumentHelper.parseText(pageSource.toString()); org.fest.assertions.Assertions.assertThat(pageSource.toString()) .contains("<input type='text' name='name_query' value='foobar'"); }

  28. Unit testing Hibernate @Test publicvoidshouldFindPeopleByName() { AnnotationConfigurationconfiguration = newAnnotationConfiguration(); Propertiesproperties = configuration.getProperties(); properties.setProperty(Environment.URL, "jdbc:h2:mem:person-dao-test;MVCC=true"); properties.setProperty(Environment.DRIVER, Driver.class.getName()); properties.setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS, ManagedSessionContext.class.getName()); properties.setProperty(Environment.HBM2DDL_AUTO, "update"); configuration.addAnnotatedClass(Person.class); SessionFactorysessionFactory = configuration.buildSessionFactory(); ManagedSessionContext.bind(sessionFactory.openSession()); HibernatePersonDaopersonDao = newHibernatePersonDao(sessionFactory); personDao.create(Person.withName("AyeBeeCee"), Person.withName("AyeCee")); sessionFactory.getCurrentSession().flush(); sessionFactory.getCurrentSession().clear(); assertThat(personDao.find("Bee")) .contains(Person.withName("AyeBeeCee")) .excludes(Person.withName("AyeCee")); ManagedSessionContext.unbind(sessionFactory).close(); }

  29. Persistence – the ORM

  30. Why? • In order to reduce the amount of dedious work and error prone SQL/jdbc code I write • As a developer who already understands SQL well, • I want to use an ORM to manage my persistence

  31. Basics @Entity publicclass Person { @Id@GeneratedValue(strategy=GenerationType.SEQUENCE) private Long id; private String name; @Override publicbooleanequals(Object obj) { } @Override publicinthashCode() { } }

  32. Advanced ORM-JPA-Hibernate

  33. Advanced: Hacked polymorphic joins @Entity@Table(name="XX_KONTO") publicclassKonto implements Serializable { @EmbeddedId private KontoPk id = new KontoPk(); @Column(name="TREKKPST") private Integer trekkprosent; @ManyToOne(optional=true)@NotFound(action=NotFoundAction.IGNORE) @JoinColumn(name="fodselsnr", referencedColumnName="fodselsnr") private Person person; @ManyToOne(optional=true) @NotFound(action=NotFoundAction.IGNORE) @JoinColumn(name="orgnr", referencedColumnName="orgnr")private Foretak foretak; public KontoEier getEier() { returnperson != null ? person : foretak; }

  34. Advanced: Composite foreign keys as part of primary key @ManyToOne @JoinColumns({ @JoinColumn(name="fylkenr", referencedColumnName="fylkenr", insertable=false, updatable=false), @JoinColumn(name="komnr2", referencedColumnName="komnr2", insertable=false, updatable=false), @JoinColumn(name="ktotype", referencedColumnName="ktotype", insertable=false, updatable=false), @JoinColumn(name="ktonr", referencedColumnName="ktonr", insertable=false, updatable=false)}) private Konto konto;

  35. Advanced: Composite foreign keys as part of primary key @ManyToOne @JoinColumns({ @JoinColumn(name="fylkenr", referencedColumnName="fylkenr", insertable=false, updatable=false), @JoinColumn(name="komnr2", referencedColumnName="komnr2", insertable=false, updatable=false), @JoinColumn(name="ktotype", referencedColumnName="ktotype", insertable=false, updatable=false), @JoinColumn(name="ktonr", referencedColumnName="ktonr", insertable=false, updatable=false)}) private Konto konto;

  36. Advanced: Fetch strategies publicenum FetchType { /** *Definesthatdatamustbelazilyfetched */ LAZY, /** *Definesthatdatamustbeeagerlyfetched */ EAGER };

  37. Always understand what the ORM does • Fetching strategies: • Left outer join • Lazy loading • Inheritance • Table-per-concrete class (union subclass) • Table-per-class (join subclass) • Table-per-class-hierarchy () • Relationships • @OneToMany @ManyToOne • Cascading (broken) • Ownership, mapped-by • When in doubt – make sure to unit test!

  38. Distributed applications

  39. Distributed applications • Fowler’s first law of distributed objects: • Don’t distribute your objects • As the server: • Treat your clients as you would a human client: Designed interface, test at the outside, have a ”designer” take a look • As the client: • Each service you use will decrease your understanding, reliability and performance

  40. Why? • In order to get access to data or a service owned by another entity • As a complex application • I want to integrate with the third party service • In order to profit on a valuable service or dataset that I control • As a service provider • I want to provide a remote API to my services • In order to create a rich client interface • As a the client side of a rich internet application • I want to communicate remotely with the server

  41. Bad reasons! • In order to reuse functionality • As a complex application • I want to call a third party internal service • (Seldom worth the saving) • In order to don’t communicate with some other developer • As an introvert loner • I want to hide myself behind a service interface • (How will you be able to assess total complexity?)

  42. How • REST vs SOAP vs ORB • REST is good when you want to use HTTP as an application protocol and not just a transport protocol • ORBs are good when you control both endpoints • SOAP is good when ORBs would be better • Hessian is a binary ORB-protocol over HTTP • Distributed transactions versus idempotent writes • Very few organizations have been able to master distributed transactions • Understand the semantics of HTTP PUT

  43. Security – Little Bobby Tables

  44. Security

  45. Security thread #1: Injection • Problem: Client tricks the application to treat data as instructions • SQL commands • HTML code • (In C: return pointer in memory) • Solution: Treat all outside data as tainted • Outside: Request (obviously), files (usually), database (yes!) • Always, alway, always escape tainted data • SQL parameters – Use PreparedStatement • Hibernate parameters – Use parameters or Criteria • HTML snippet – escape

  46. Security threat #2: Client-only validation • Attack: A malicious user looks at a form and changes the parameters en-route (Firefox plugin) • Weakness: The server expects incoming data to be valid • Solution (again): Treat all incoming data as tainted

  47. Security threat #3: Request forgery • Problem: A malicious site tricks the user into submitting a rogue post-request to you • Problem: A malicious email tricks the user into clicking a rogue link to your application • Solution (again): Treat all incoming data as tainted

  48. Client options HTML GWT Flex (or Silverlight :-P) JavaFX Swing

  49. Things to consider • Power of expression • Flex, JavaFX, GWT • Testing round-trip • HTML, Swing, (JavaFX?) • Easy to layout good Uis? • Flex, JavaFX(?) • Simplicity of language • Swing, GWT • Client pervasiveness/perceived ease of installation • HTML, GWT, (Flex) • Client performance requirements • HTML, (GWT)

  50. Things that aren’t issues any more • Communication between client and server • Basically, all use http-based async ORBs • With Swing: Make your own async http ORB a la GWT with SwingWorker and Hessian • Distribution of client • Swing and JavaFX use JavaWebStart

More Related