Skip to content

Commit 0632710

Browse files
committed
add passing data from server to react render Server/Client functions
1 parent 1267fe1 commit 0632710

16 files changed

+134
-50
lines changed

build.gradle

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ repositories { jcenter() }
2222
dependencies {
2323
compile 'org.springframework.boot:spring-boot-starter-actuator',
2424
'org.springframework.boot:spring-boot-starter-mustache',
25+
'org.springframework.boot:spring-boot-starter-data-rest',
26+
'org.springframework.boot:spring-boot-starter-data-jpa',
2527
'org.springframework.boot:spring-boot-devtools',
2628
'org.projectlombok:lombok'
27-
29+
runtime 'com.h2database:h2'
2830
testCompile 'org.springframework.boot:spring-boot-starter-test'
2931
}
3032

src/main/java/daggerok/ReactServerSideRenderingSpringBootApplication.java

+14
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
11
package daggerok;
22

3+
import daggerok.domain.Post;
4+
import daggerok.domain.PostRestRepository;
5+
import daggerok.domain.RestRepositoryConfig;
6+
import org.springframework.boot.CommandLineRunner;
37
import org.springframework.boot.SpringApplication;
48
import org.springframework.boot.autoconfigure.SpringBootApplication;
9+
import org.springframework.context.annotation.Bean;
10+
import org.springframework.context.annotation.Import;
11+
12+
import java.util.stream.Stream;
513

614
@SpringBootApplication
15+
@Import(RestRepositoryConfig.class)
716
public class ReactServerSideRenderingSpringBootApplication {
817

18+
@Bean
19+
public CommandLineRunner testData(PostRestRepository posts) {
20+
return args -> Stream.of("one", "two", "3").map(Post::of).forEach(posts::save);
21+
}
22+
923
public static void main(String[] args) {
1024
SpringApplication.run(ReactServerSideRenderingSpringBootApplication.class, args);
1125
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package daggerok.domain;
2+
3+
import lombok.Data;
4+
import lombok.NoArgsConstructor;
5+
import lombok.NonNull;
6+
import lombok.RequiredArgsConstructor;
7+
8+
import javax.persistence.Entity;
9+
import javax.persistence.GeneratedValue;
10+
import javax.persistence.Id;
11+
import java.io.Serializable;
12+
13+
/**
14+
* Created by mak on 9/13/16.
15+
*/
16+
@Data
17+
@Entity
18+
@NoArgsConstructor
19+
@RequiredArgsConstructor(staticName = "of")
20+
public class Post implements Serializable {
21+
22+
@Id @GeneratedValue Long id;
23+
@NonNull String text;
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package daggerok.domain;
2+
3+
import org.springframework.data.jpa.repository.JpaRepository;
4+
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
5+
6+
/**
7+
* Created by mak on 9/13/16.
8+
*/
9+
@RepositoryRestResource
10+
public interface PostRestRepository extends JpaRepository<Post, Long> {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package daggerok.domain;
2+
3+
import org.springframework.context.annotation.Configuration;
4+
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
5+
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;
6+
7+
/**
8+
* Created by mak on 9/13/16.
9+
*/
10+
@Configuration
11+
public class RestRepositoryConfig extends RepositoryRestConfigurerAdapter {
12+
13+
@Override
14+
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
15+
config.exposeIdsFor(Post.class);
16+
}
17+
}

src/main/java/daggerok/react/React.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package daggerok.react;
22

3+
import daggerok.domain.Post;
34
import lombok.SneakyThrows;
45
import lombok.val;
56
import org.springframework.stereotype.Component;
@@ -9,6 +10,7 @@
910
import javax.script.ScriptEngineManager;
1011
import java.io.InputStreamReader;
1112
import java.io.Reader;
13+
import java.util.List;
1214

1315
/**
1416
* Created by mak on 9/7/16.
@@ -31,9 +33,9 @@ private void init() {
3133
}
3234

3335
@SneakyThrows
34-
public String renderApp() {
36+
public String renderApp(List<Post> posts) {
3537

36-
val html = call("renderServer");
38+
val html = call("renderServer", posts);
3739

3840
return String.valueOf(html);
3941
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package daggerok.react;
22

3-
import org.springframework.beans.factory.annotation.Autowired;
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import daggerok.domain.PostRestRepository;
5+
import lombok.SneakyThrows;
6+
import lombok.val;
47
import org.springframework.stereotype.Controller;
58
import org.springframework.ui.Model;
69
import org.springframework.web.bind.annotation.GetMapping;
@@ -11,11 +14,24 @@
1114
@Controller
1215
public class ReactServerSideRenderingController {
1316

14-
@Autowired React react;
17+
final React react;
18+
final PostRestRepository postRestRepository;
19+
final ObjectMapper objectMapper;
20+
21+
public ReactServerSideRenderingController(React react,
22+
PostRestRepository postRestRepository,
23+
ObjectMapper objectMapper) {
24+
this.react = react;
25+
this.postRestRepository = postRestRepository;
26+
this.objectMapper = objectMapper;
27+
}
1528

1629
@GetMapping("/")
30+
@SneakyThrows
1731
public String index(Model model) {
18-
model.addAttribute("data", react.renderApp());
32+
val posts = postRestRepository.findAll();
33+
model.addAttribute("data", react.renderApp(posts));
34+
model.addAttribute("posts", objectMapper.writeValueAsString(posts));
1935
return "index";
2036
}
2137
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
spring.mustache.suffix=.hbs
2+
spring.mustache.cache=false
3+
spring.mustache.expose-spring-macro-helpers=true
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>server-side-react-spring-boot</title>
6+
<link href="{{springMacroRequestContext.request.contextPath}}/favicon.ico" rel="shortcut icon">
7+
<link href="{{springMacroRequestContext.request.contextPath}}/app.css" rel="stylesheet"></head>
8+
<body class="container">
9+
<!-- 1) render data from backend server side (see daggerok.react.ReactServerSideRenderingController.index) -->
10+
<div id="app">{{{html}}}</div>
11+
<script src="{{springMacroRequestContext.request.contextPath}}/app.js"></script>
12+
<!-- 2) up and running dynamic part of application after it static initial page was loader -->
13+
<script type="text/javascript">
14+
$(function() {
15+
renderClient({{{json}}});
16+
});
17+
</script>
18+
</body>
19+
</html>

src/main/resources/templates/index.html

-18
This file was deleted.

ui/config/webpack.config.babel.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const config = {
5959
include: bsInclude,
6060
loader: 'url?limit=4096&mimetype=application/octet-stream'
6161
}, {
62-
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
62+
test: /\.(ico|svg)(\?v=\d+\.\d+\.\d+)?$/,
6363
include: bsInclude,
6464
loader: 'url?limit=4096&mimetype=image/svg+xml'
6565
}, {
@@ -74,7 +74,10 @@ const config = {
7474
},
7575
plugins: [
7676
new ExtractPlugin('/[name].css', { allChunks: true }),
77-
new HtmlWebpackPlugin({ template: './src/assets/index.hbs' })
77+
new HtmlWebpackPlugin({
78+
template: './src/assets/index.hbs',
79+
favicon: './src/assets/favicon.ico'
80+
})
7881
],
7982
postcss: [ autoprefixer({ browsers: ['last 2 versions'] }) ],
8083
devtool: '#cheap-module-inline-source-map',

ui/package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@
6161
"bootstrap": "*",
6262
"jquery": "*",
6363
"react": "*",
64-
"react-dom": "*",
65-
"react-router": "*"
64+
"react-dom": "*"
6665
},
6766
"babel": {
6867
"presets": [

ui/src/assets/favicon.ico

1.12 KB
Binary file not shown.

ui/src/components/Main.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
import React from 'react';
55
import Nav from "./Nav";
66

7-
export default () => (
7+
export default ({posts}) => (
88
<div>
99
<span>main component</span>
1010
<Nav/>
11+
<ul>
12+
{posts ? posts.map((post, i) => <li key={i}>{post.id}) {post.text}</li>) : <li>empty</li>}
13+
</ul>
1114
</div>
1215
);

ui/src/components/Nav.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22
* Created by mak on 9/6/16.
33
*/
44
import React from 'react';
5-
import { Link } from 'react-router';
65

76
export default () => (
87
<ul>
9-
<li><Link to="/">root</Link></li>
10-
<li><Link to="/home">home</Link></li>
11-
<li><Link to="/not-found">not-found</Link></li>
8+
<li><a href="/">root</a></li>
9+
<li><a href="/">home</a></li>
10+
<li><a href="/not-found">not-found</a></li>
1211
</ul>
1312
);

ui/src/main.js

+8-17
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@ import './assets';
55

66
import React, { Component } from "react";
77
import { render } from "react-dom";
8-
import { Router, Route, IndexRoute, browserHistory, Link } from 'react-router';
9-
10-
import NotFound from "./components/NotFound";
118
import Main from "./components/Main";
129

1310
class App extends Component {
@@ -40,26 +37,20 @@ class App extends Component {
4037
}
4138
}
4239

43-
global.renderClient = function() {
44-
// const renderClient = (data) => {
45-
// const data = data || [];
40+
global.renderClient = function(json) {
41+
const posts = json || [];
42+
// console.log('client posts', JSON.stringify(posts));
4643
return render(
47-
<Router history={browserHistory}>
48-
<Route path="/" component={App}>
49-
<IndexRoute component={Main}/>
50-
<Route path="home" component={Main}/>
51-
<Route path="*" component={NotFound}/>
52-
</Route>
53-
</Router>,
44+
<App><Main posts={posts}/></App>,
5445
document.getElementById('app')
5546
);
5647
};
5748

5849
import { renderToString } from 'react-dom/server'
59-
global.renderServer = function() {
60-
// const renderServer = (data) => {
61-
// const data = Java.from(data);
62-
return renderToString(<App><Main/></App>);
50+
global.renderServer = function(java) {
51+
const posts = Java.from(java || []);
52+
// console.log('server posts', posts);
53+
return renderToString(<App><Main posts={posts}/></App>);
6354
};
6455

6556
import $ from 'jquery';

0 commit comments

Comments
 (0)