Presentation is loading. Please wait.

Presentation is loading. Please wait.

Farewell Old Application Server The Server Container Anti- Pattern and how to avoid it.

Similar presentations


Presentation on theme: "Farewell Old Application Server The Server Container Anti- Pattern and how to avoid it."— Presentation transcript:

1 Farewell Old Application Server The Server Container Anti- Pattern and how to avoid it

2 (Shameless plug)

3

4

5

6 .meetup.com/13

7 Why am I standing here?

8 I believe

9 that you, as a developer,

10 should care about deployment.

11 Two things you will learn:

12 1. How to create a non-server

13 2. Practical Configuration Management

14 My story:

15 By company decree

16 we were using a traditional application server.

17 (WebSphere)

18 Unhappily.

19 It was ”somebody else’s problem.”

20 We couldn’t do what we wanted.

21 (Continuous deployment!)

22 Complexity was killing our projects.

23 We started caring.

24 We decided to cut the Gordian knot.

25 Our solution:

26 Standard Java Maven Jetty

27 Let’s see how it works.

28 Example application

29

30

31

32 Can’t change parent!

33 A developer has released a new version (1.0.1).

34 Create a test environment and try it out.

35 Server: Initial installation

36

37

38

39

40 ./install.sh 1.0.1

41 Preproduction environment

42 Server: Upgrade production

43

44

45 Production environment

46

47 Lesson learned: Package everything you need.

48 Experience: Separate information that should survive upgrades.

49 Symbolic link

50 port=9090 shutdown_port=9190 datasource.url=jdbc:mysql://localhost/nocontainer_dev datasource.username=johannes datasource.password=johannes

51 New requirement: Delete

52 Testing: Embedded integration test

53 public void testDeleteCategory() throws Exception { // Insert test data Category category = new Category(uniqueName()); Serializable key = getRepo().insert(category); getRepo().writeChanges(); // Ensure that data is displayed in index beginAt("categories/list.html"); assertTextPresent("Showing all categories"); assertLinkPresentWithText(category.getName()); // Delete it beginAt("categories/edit.html?id=" + key); submit("delete"); // Ensure that after delete, we go to index assertTextPresent("Showing all categories"); // Ensure that the category is no longer there assertLinkNotPresentWithText(category.getName()); }

54 public void testDeleteCategory() throws Exception { // Insert test data Category category = new Category(uniqueName()); Serializable key = getRepo().insert(category); getRepo().writeChanges(); // Ensure that data is displayed in index beginAt("categories/list.html"); assertTextPresent("Showing all categories"); assertLinkPresentWithText(category.getName()); // Delete it // Ensure that the category is no longer there assertLinkNotPresentWithText(category.getName()); }

55 public void testDeleteCategory() throws Exception { // Insert test data // Ensure that data is displayed in index // Delete it beginAt("categories/edit.html?id=" + key); submit("delete"); // Ensure that after delete, we go to index assertTextPresent("Showing all categories"); // Ensure that the category is no longer there }

56 public void testDeleteCategory() throws Exception { // Insert test data // Ensure that data is displayed in index // Delete it beginAt("categories/edit.html?id=" + key); submit("delete"); // Ensure that after delete, we go to index assertTextPresent("Showing all categories"); // Ensure that the category is no longer there }

57

58 ${category.name} #showErrors("category") Parent: #selectForObject("category.parent" $allCategories) Description: #springFormInput("category.description" "") #springShowErrors(" " "") Type: #selectForEnum("category.type" $categoryTypes) List all

59 ${category.name} #showErrors("category") Parent: #selectForObject("category.parent" $allCategories) Description: #springFormInput("category.description" "") #springShowErrors(" " "") Type: #selectForEnum("category.type" $categoryTypes) List all

60

61 public void testDeleteCategory() throws Exception { // Insert test data // Ensure that data is displayed in index // Delete it beginAt("categories/edit.html?id=" + key); submit("delete"); // Ensure that after delete, we go to index assertTextPresent("Showing all categories"); // Ensure that the category is no longer there }

62 Debugging: Just like a main method

63 protected ModelAndView onSubmit( HttpServletRequest req, HttpServletResponse resp, Object command, BindException errors) { Category category = (Category)command; if (category.getId() == null) { Serializable key = repository.insert(category); return new ModelAndView(new RedirectView("show.html?id=" + key)); } repository.update(category); // Redirect on post - go back to the same page return new ModelAndView( new RedirectView(req.getRequestURI() + "?" + req.getQueryString())); }

64 protected ModelAndView onSubmit( HttpServletRequest req, HttpServletResponse resp, Object command, BindException errors) { Category category = (Category)command; if (category.getId() == null) { Serializable key = repository.insert(category); return new ModelAndView(new RedirectView("show.html?id=" + key)); } if (req.getParameter("delete") != null) { repository.delete(Category.class, category.getId()); return new ModelAndView(new RedirectView("list.html")); } repository.update(category); // Redirect on post - go back to the same page return new ModelAndView( new RedirectView(req.getRequestURI() + "?" + req.getQueryString())); }

65

66

67 Continuous integration

68 (Not demoed)

69

70

71 mvn deploy

72

73 Continuous Deployment

74

75 The Simplest Thing...

76 ... cron

77 Mon Sep 10 18:37:02 EDT 2007: Not upgraded, skipping restart Mon Sep 10 18:38:13 EDT 2007: Installed new version Stopping Starting Testing connection (user=johannes, url=jdbc:mysql://localhost/nocontainer_dev)... OK! Deploy 'nocontainer' from /home/nocontainer/test/nocontainer- app/curr/repo/com/b rodwall/nocontainer/nocontainer-web/1.1- SNAPSHOT/nocontainer-web-1.1-SNAPSHOT.wa r Server started on http://localhost:9090 in 12.547s Mon Sep 10 18:39:02 EDT 2007: Not upgraded, skipping restart

78 Experience: Look like a UNIX service

79 ./prod/nocontainer-app/operate.sh start./prod/nocontainer-app/operate.sh stop./prod/nocontainer-app/operate.sh status

80 Release: mvn release

81

82 Upgrading staging server to 1.0.2

83 Upgrading production server to 1.0.2

84

85 Summary

86 1.Add a test

87 2. Make it pass

88 3. Check it in

89 4. Continuous integration and deployment

90 5. Run it at test server

91 6. Deploy to staging

92 6. Final verifications

93 7. Deploy to production

94 Results:

95 1. Better management

96 2. Simplicity

97 3. Isolation

98 4. Better development support

99 1: Single commands to...

100 ... Build

101 ... Install

102 ... Upgrade

103 => Ease of deployment

104 2: A simpler environment

105 ... No dependencies between servers

106 ... We own the Main class

107 Scripted server acts as UNIX service.

108 Upgrade with ssh, cron

109 Avoid EJBs, JMS, XA

110 3: Better isolation between applications

111 (especially: JVM version)

112 The ultimate irony:

113 JPA (EJB 3) via Hibernate on Java SE > 1.5

114 Our WebSphere servers still don’t support 1.5

115 Avoid Java EE server to get Java EE features

116 4: Better development attributes

117 Embedded integration tests

118 Easier to debug on server

119 Exact same software in debugger and server

120 Same versions of all libraries

121 Free, low footprint installation on workstation

122 Challenges:

123 How ready is Jetty for production?

124 What is being run in the wild?

125 Jetty: 221k

126

127

128 (Okay, then)

129

130 Load balancing and failover

131

132 (No state in application server)

133 Two week intensive stress testing

134 We could not make it fail

135 Organization: Open source procurement process

136 Organization: Showing this to the WebSphere guys

137 Support: Per project

138 Application management shortcomings

139 ”On what servers is this application running?”

140 ”What applications are running on this server”

141 Making: ”jettyctl”

142 Requires some documentation

143 Don’t go overboard with management

144 YAGNI

145 Why Anti-pattern

146 Insufficent isolation means risk

147 Insufficient isolation means older versions

148 Outside-in means lack of control

149 Outside-in means lack of understanding

150 Outside-in means complexity

151 Deployment apps means manual work

152 Conclusion:

153 In Soviet Russia, Application Server contains you!

154 We have turned the app server inside out

155 We choose Jetty, Maven, mod_proxy

156 These worked for us

157 (You may prefer glassfish, webstone or whatever)

158 (Shameless plug)

159 Q&A


Download ppt "Farewell Old Application Server The Server Container Anti- Pattern and how to avoid it."

Similar presentations


Ads by Google