Skip to content

Commit 2b4a52b

Browse files
committed
Add Spring Boot example app with auto-configuration demo
- New subproject: python-embed-examples/spring-boot-example/ - REST controller (/eval, /exec, /info) using auto-configured PythonEmbed bean - Actuator health endpoint with PythonEmbedHealthIndicator - SINGLE mode (application.yml) and POOL mode (application-pool.yml) profiles - Updated examples settings.gradle to include spring-boot-starter and new subproject
1 parent 34c26f5 commit 2b4a52b

6 files changed

Lines changed: 157 additions & 0 deletions

File tree

python-embed-examples/settings.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ rootProject.name = 'python-embed-examples'
33
includeBuild '../python-embed-gradle-plugin'
44
include ':python-embed-runtime'
55
project(':python-embed-runtime').projectDir = file('../python-embed-runtime')
6+
include ':python-embed-spring-boot-starter'
7+
project(':python-embed-spring-boot-starter').projectDir = file('../python-embed-spring-boot-starter')
68

79
include 'basic-eval'
810
include 'numpy-basic'
@@ -16,3 +18,4 @@ include 'object-handle'
1618
include 'health-monitor'
1719
include 'batch-operations'
1820
include 'pandas-dataframe'
21+
include 'spring-boot-example'
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
plugins {
2+
id 'io.github.howtis.python-embed'
3+
id 'org.springframework.boot' version '3.3.5'
4+
id 'io.spring.dependency-management' version '1.1.6'
5+
}
6+
7+
application {
8+
mainClass = 'io.github.howtis.pythonembed.examples.SpringBootExampleApplication'
9+
}
10+
11+
dependencies {
12+
implementation project(':python-embed-runtime')
13+
implementation project(':python-embed-spring-boot-starter')
14+
implementation 'org.springframework.boot:spring-boot-starter-web'
15+
implementation 'org.springframework.boot:spring-boot-starter-actuator'
16+
}
17+
18+
pythonEmbed {
19+
packages = ['msgpack']
20+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package io.github.howtis.pythonembed.examples;
2+
3+
import io.github.howtis.pythonembed.PythonEmbed;
4+
import org.springframework.web.bind.annotation.GetMapping;
5+
import org.springframework.web.bind.annotation.RequestParam;
6+
import org.springframework.web.bind.annotation.RestController;
7+
8+
import java.util.Map;
9+
10+
/**
11+
* REST controller demonstrating auto-configured {@link PythonEmbed} bean
12+
* injection and usage.
13+
*/
14+
@RestController
15+
public class PythonController {
16+
17+
private final PythonEmbed pythonEmbed;
18+
19+
public PythonController(PythonEmbed pythonEmbed) {
20+
this.pythonEmbed = pythonEmbed;
21+
}
22+
23+
/**
24+
* Evaluates a Python expression and returns the result.
25+
*
26+
* <pre>
27+
* GET /eval?expr=2+2 → 4
28+
* GET /eval?expr=len('abc') → 3
29+
* </pre>
30+
*/
31+
@GetMapping("/eval")
32+
public Map<String, Object> eval(@RequestParam String expr) {
33+
String result;
34+
try {
35+
var value = pythonEmbed.eval(expr);
36+
result = value.toJson();
37+
} catch (Exception e) {
38+
result = "Error: " + e.getMessage();
39+
}
40+
return Map.of("expression", expr, "result", result);
41+
}
42+
43+
/**
44+
* Executes a Python statement.
45+
*
46+
* <pre>
47+
* GET /exec?stmt=x=42
48+
* GET /eval?expr=x → 42 (shared namespace)
49+
* </pre>
50+
*/
51+
@GetMapping("/exec")
52+
public Map<String, Object> exec(@RequestParam String stmt) {
53+
try {
54+
pythonEmbed.exec(stmt);
55+
return Map.of("statement", stmt, "status", "ok");
56+
} catch (Exception e) {
57+
return Map.of("statement", stmt, "status", "error", "message", e.getMessage());
58+
}
59+
}
60+
61+
/**
62+
* Returns Python interpreter information.
63+
*/
64+
@GetMapping("/info")
65+
public Map<String, String> info() {
66+
pythonEmbed.exec("import sys");
67+
String version = pythonEmbed.eval("sys.version").asString();
68+
String executable = pythonEmbed.eval("sys.executable").asString();
69+
return Map.of("version", version, "executable", executable);
70+
}
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package io.github.howtis.pythonembed.examples;
2+
3+
import io.github.howtis.pythonembed.PythonEmbed;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import org.springframework.boot.CommandLineRunner;
7+
import org.springframework.boot.SpringApplication;
8+
import org.springframework.boot.autoconfigure.SpringBootApplication;
9+
import org.springframework.context.annotation.Bean;
10+
11+
/**
12+
* Demonstrates Spring Boot auto-configuration for python-embed.
13+
*
14+
* <p>Starts a web server with a REST controller ({@link PythonController})
15+
* and Actuator health endpoint backed by {@code PythonEmbedHealthIndicator}.
16+
*/
17+
@SpringBootApplication
18+
public class SpringBootExampleApplication {
19+
20+
private static final Logger log = LoggerFactory.getLogger(SpringBootExampleApplication.class);
21+
22+
public static void main(String[] args) {
23+
SpringApplication.run(SpringBootExampleApplication.class, args);
24+
}
25+
26+
@Bean
27+
CommandLineRunner demo(PythonEmbed pythonEmbed) {
28+
return args -> {
29+
log.info("Auto-configured PythonEmbed bean: {}", pythonEmbed);
30+
pythonEmbed.exec("import sys");
31+
log.info("Python version: {}", pythonEmbed.eval("sys.version").asString());
32+
log.info("Ping: {}", pythonEmbed.ping());
33+
};
34+
}
35+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
python-embed:
2+
mode: POOL
3+
pool:
4+
min: 2
5+
max: 4
6+
idle-timeout: 60s
7+
health-check-interval: 30s
8+
close-timeout: 10s
9+
10+
management:
11+
endpoint:
12+
health:
13+
show-details: always
14+
endpoints:
15+
web:
16+
exposure:
17+
include: health,info
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
python-embed:
2+
mode: SINGLE
3+
4+
management:
5+
endpoint:
6+
health:
7+
show-details: always
8+
endpoints:
9+
web:
10+
exposure:
11+
include: health,info

0 commit comments

Comments
 (0)