This repository was archived by the owner on Mar 24, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathServer.java
More file actions
executable file
·139 lines (126 loc) · 5.53 KB
/
Server.java
File metadata and controls
executable file
·139 lines (126 loc) · 5.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package benchmarks;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executors;
import javax.sql.DataSource;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import httl.Engine;
import httl.Template;
public class Server {
private static final String HELLO_TEXT = "Hello, World!";
private static final byte[] HELLO_BYTES = HELLO_TEXT.getBytes();
private static final int HELLO_LENGTH = HELLO_BYTES.length;
private static final String SERVER_NAME = "httpserver-robaho";
private static List<Fortune> queryFortunes(DataSource ds) throws SQLException {
List<Fortune> fortunes = new ArrayList<>();
try (Connection conn = ds.getConnection();
PreparedStatement statement = conn.prepareStatement("SELECT id, message FROM fortune");
ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next())
fortunes.add(new Fortune(resultSet.getInt(1), resultSet.getString(2)));
}
return fortunes;
}
private static DataSource createPostgresDataSource() throws ClassNotFoundException {
Class.forName("org.postgresql.Driver");
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:postgresql://tfb-database:5432/hello_world");
config.setUsername("benchmarkdbuser");
config.setPassword("benchmarkdbpass");
config.setMaximumPoolSize(512);
return new HikariDataSource(config);
}
private static Template loadTemplate(String filename) throws IOException, ParseException {
Properties props = new Properties();
props.put("import.packages", "java.util," + Fortune.class.getPackage().getName());
props.put("input.encoding", "UTF-8");
props.put("output.encoding", "UTF-8");
props.put("precompiled", "false");
Engine engine = Engine.getEngine(props);
return engine.getTemplate(filename);
}
private static HttpHandler createPlaintextHandler() {
return t -> {
t.getResponseHeaders().add("Content-Type", "text/plain");
t.getResponseHeaders().add("Server", SERVER_NAME);
t.sendResponseHeaders(200, HELLO_LENGTH);
t.getResponseBody().write(HELLO_BYTES);
t.getResponseBody().close();
};
}
private static HttpHandler createJSONHandler() {
return t -> {
Message m = new Message(HELLO_TEXT);
t.getResponseHeaders().add("Content-Type", "application/json");
t.getResponseHeaders().add("Server", SERVER_NAME);
var bos = new ByteArrayOutputStream();
OutputStreamWriter w = new OutputStreamWriter(bos);
m.writeJSONString(w);
w.flush();
t.sendResponseHeaders(200, bos.size());
bos.writeTo(t.getResponseBody());
t.getResponseBody().close();
};
}
private static HttpHandler createFortunesHandler(DataSource ds) throws IOException, ParseException {
Template template = loadTemplate("/fortunes.template.httl");
return t -> {
try {
// query db
List<Fortune> fortunes = queryFortunes(ds);
fortunes.add(new Fortune(0, "Additional fortune added at request time."));
Collections.sort(fortunes);
// render template
Map<String, Object> context = new HashMap<>(1);
context.put("fortunes", fortunes);
ByteArrayOutputStream out = new ByteArrayOutputStream();
template.render(context, out);
byte[] bytes = out.toByteArray();
// send response
t.getResponseHeaders().add("Content-Type", "text/html; charset=utf-8");
t.getResponseHeaders().add("Server", SERVER_NAME);
t.sendResponseHeaders(200, bytes.length);
t.getResponseBody().write(bytes);
t.getResponseBody().close();
} catch (SQLException | ParseException e) {
throw new IOException(e);
}
};
}
public static void main(String[] args) throws Exception {
// parse arguments
String settings = args.length > 0 ? args[0] : "";
int port = args.length > 1 ? Integer.parseInt(args[1]) : 8080;
if (settings.contains("debug"))
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "DEBUG");
// create server
HttpServer server = HttpServer.create(new InetSocketAddress(port), 1024 * 8);
server.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
// server.setExecutor(Executors.newCachedThreadPool());
// add context handlers
server.createContext("/plaintext", createPlaintextHandler());
server.createContext("/json", createJSONHandler());
if (settings.contains("postgres")) {
DataSource ds = createPostgresDataSource();
server.createContext("/fortunes", createFortunesHandler(ds));
}
// start server
server.start();
}
}