Download presentation
Presentation is loading. Please wait.
Published byBertram Hunt Modified over 9 years ago
1
Farewell Old Application Server The Server Container Anti- Pattern and how to avoid it
2
(Shameless plug)
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
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
40
./install.sh 1.0.1
41
Preproduction environment
42
Server: Upgrade production
45
Production environment
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 }
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
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())); }
67
Continuous integration
68
(Not demoed)
71
mvn deploy
73
Continuous Deployment
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
82
Upgrading staging server to 1.0.2
83
Upgrading production server to 1.0.2
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
128
(Okay, then)
130
Load balancing and failover
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
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.