├── node-frontend ├── .env ├── .env.development.local ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── manifest.json │ └── index.html ├── src │ ├── index.css │ ├── index.js │ ├── App.js │ ├── App.css │ ├── setupProxy.js │ ├── components │ │ ├── PostList.js │ │ ├── Post.js │ │ └── PostInput.js │ └── serviceWorker.js ├── .gitignore ├── index.js └── package.json ├── topology.png ├── codeready-workspaces-preview.png ├── quarkus-backend ├── src │ └── main │ │ ├── resources │ │ ├── application.properties │ │ └── META-INF │ │ │ └── resources │ │ │ └── index.html │ │ └── java │ │ └── org │ │ └── eclipse │ │ └── chedemos │ │ ├── PostResource.java │ │ └── Post.java └── pom.xml ├── dockerfiles ├── data-copy.sh └── Dockerfile-data ├── .gitignore ├── README.md ├── README-che.md ├── package-local.devfile.yaml ├── .che-didact-guide.md ├── che-devfile.yaml ├── devfile.yaml ├── LICENSE └── factory-contribute.svg /node-frontend/.env: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /node-frontend/.env.development.local: -------------------------------------------------------------------------------- 1 | DANGEROUSLY_DISABLE_HOST_CHECK=true 2 | -------------------------------------------------------------------------------- /node-frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-developer-demos/quarkus-reactjs-postit-app/HEAD/topology.png -------------------------------------------------------------------------------- /codeready-workspaces-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-developer-demos/quarkus-reactjs-postit-app/HEAD/codeready-workspaces-preview.png -------------------------------------------------------------------------------- /node-frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-developer-demos/quarkus-reactjs-postit-app/HEAD/node-frontend/public/favicon.ico -------------------------------------------------------------------------------- /node-frontend/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /quarkus-backend/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | quarkus.mongodb.connection-string=${uri} 2 | quarkus.mongodb.credentials.username=${username} 3 | quarkus.mongodb.credentials.password=${password} 4 | quarkus.mongodb.database=sampledb 5 | 6 | # final jar is uber and without suffix so it works with odo without additional param 7 | quarkus.package.uber-jar=true 8 | -------------------------------------------------------------------------------- /node-frontend/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /node-frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /node-frontend/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const setupProxy = require('./src/setupProxy'); 3 | const path = require('path') 4 | const app = express() 5 | 6 | 7 | // serving react app 8 | app.use(express.static(path.join(__dirname, 'build'))) 9 | app.get('/', (req, res) => { 10 | res.sendFile(path.join(__dirname, 'build', 'index.html')) 11 | }) 12 | 13 | 14 | setupProxy(app); 15 | 16 | 17 | 18 | var port = '8080' 19 | if (process.env.FRONTEND_PORT) { 20 | port = process.env.FRONTEND_PORT; 21 | } 22 | 23 | app.listen(port) 24 | 25 | -------------------------------------------------------------------------------- /node-frontend/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | import 'bootstrap/dist/css/bootstrap.min.css'; 8 | 9 | ReactDOM.render(, document.getElementById('root')); 10 | 11 | // If you want your app to work offline and load faster, you can change 12 | // unregister() to register() below. Note this comes with some pitfalls. 13 | // Learn more about service workers: https://bit.ly/CRA-PWA 14 | serviceWorker.unregister(); 15 | -------------------------------------------------------------------------------- /node-frontend/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './App.css'; 3 | import PostInput from './components/PostInput' 4 | import PostList from './components/PostList' 5 | import Container from 'react-bootstrap/Container' 6 | import Row from 'react-bootstrap/Row' 7 | 8 | function App() { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | ); 22 | } 23 | 24 | export default App; 25 | 26 | -------------------------------------------------------------------------------- /node-frontend/src/App.css: -------------------------------------------------------------------------------- 1 | .post-input { 2 | padding: 25px; 3 | margin: 15px 0 30px 0; 4 | border-width: .2rem .2rem 0; 5 | border-radius: 8px; 6 | border: .2rem solid #ececec; 7 | } 8 | 9 | .post-title { 10 | font-size: 2rem; 11 | padding-bottom: 0.5rem; 12 | } 13 | 14 | .post-content { 15 | color: #444; 16 | font-size: 1.25rem; 17 | } 18 | 19 | .post-time { 20 | margin-top: 15px; 21 | color: #888; 22 | } 23 | 24 | .delete-post-button { 25 | margin-right: 15px; 26 | } 27 | 28 | .post { 29 | padding: 15px; 30 | margin-bottom: 15px; 31 | border-width: .2rem .2rem 0; 32 | border-radius: 8px; 33 | border: .2rem solid #ececec; 34 | width: 100%; 35 | } -------------------------------------------------------------------------------- /dockerfiles/data-copy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ ! -d /work/volumes/.m2/repository ]; then 3 | mkdir -p /work/volumes/.m2/repository; 4 | cp -rf /work/m2repo/* /work/volumes/.m2/repository/; 5 | fi 6 | 7 | if [ ! -d /projects/quarkus-reactjs-postit-app/node-frontend/node_modules ]; then 8 | while [ ! -d /projects/quarkus-reactjs-postit-app/node-frontend ]; do 9 | echo '/projects/quarkus-reactjs-postit-app/node-frontend folder not created yet ...retry in 1sec'; 10 | sleep 1; 11 | done 12 | sleep 5; 13 | echo 'copying /work/node_modules/* to /projects/quarkus-reactjs-postit-app/node-frontend/node_modules'; 14 | cd /projects/quarkus-reactjs-postit-app/node-frontend/; 15 | tar -zxvf /work/node_modules.tar.gz 16 | fi 17 | sleep infinity 18 | 19 | -------------------------------------------------------------------------------- /node-frontend/src/setupProxy.js: -------------------------------------------------------------------------------- 1 | const { createProxyMiddleware } = require('http-proxy-middleware'); 2 | 3 | module.exports = function (app) { 4 | 5 | // gateway post to local quarkus 6 | var backend_quarkus_host = 'localhost'; 7 | var backend_quarkus_port = '8080'; 8 | 9 | if (process.env.COMPONENT_QUARKUS_BACKEND_HOST) { 10 | backend_quarkus_host = process.env.COMPONENT_QUARKUS_BACKEND_HOST; 11 | } 12 | 13 | if (process.env.COMPONENT_QUARKUS_BACKEND_PORT) { 14 | backend_quarkus_port = process.env.COMPONENT_QUARKUS_BACKEND_PORT; 15 | } 16 | 17 | app.use( 18 | '/posts', 19 | createProxyMiddleware({ 20 | target: `http://${backend_quarkus_host}:${backend_quarkus_port}`, 21 | changeOrigin: true 22 | }) 23 | ); 24 | 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | target/ 26 | pom.xml.tag 27 | pom.xml.releaseBackup 28 | pom.xml.versionsBackup 29 | pom.xml.next 30 | release.properties 31 | dependency-reduced-pom.xml 32 | buildNumber.properties 33 | .mvn/timing.properties 34 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 35 | .mvn/wrapper/maven-wrapper.jar 36 | 37 | .project 38 | .classpath 39 | .settings 40 | .factorypath 41 | 42 | node-frontend/build 43 | node-frontend/node_modules 44 | -------------------------------------------------------------------------------- /quarkus-backend/src/main/java/org/eclipse/chedemos/PostResource.java: -------------------------------------------------------------------------------- 1 | package org.eclipse.chedemos; 2 | 3 | import javax.ws.rs.Consumes; 4 | import javax.ws.rs.DELETE; 5 | import javax.ws.rs.GET; 6 | import javax.ws.rs.POST; 7 | import javax.ws.rs.Path; 8 | import javax.ws.rs.Produces; 9 | import javax.ws.rs.core.MediaType; 10 | import javax.ws.rs.core.Response; 11 | 12 | 13 | @Path("/posts") 14 | @Produces(MediaType.APPLICATION_JSON) 15 | @Consumes(MediaType.APPLICATION_JSON) 16 | public class PostResource { 17 | 18 | public PostResource() { 19 | } 20 | 21 | @GET 22 | public Response list() { 23 | return Response.ok(Post.listAll()).build(); 24 | } 25 | 26 | @POST 27 | public Response add(Post post) { 28 | post.persist(); 29 | return Response.ok(Post.listAll()).build(); 30 | } 31 | 32 | @DELETE 33 | public Response delete(Post post) { 34 | post.delete();; 35 | return Response.ok().build(); 36 | } 37 | } -------------------------------------------------------------------------------- /node-frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend-demo", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "bootstrap": "^5.3.2", 7 | "express": "^4.18.2", 8 | "http-proxy-middleware": "^2.0.6", 9 | "react": "^18.2.0", 10 | "react-bootstrap": "^2.9.1", 11 | "react-dom": "^18.2.0", 12 | "react-scripts": "^5.0.1" 13 | }, 14 | "scripts": { 15 | "start": "node index.js", 16 | "devmode": "react-scripts start", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject", 19 | "install": "react-scripts build" 20 | }, 21 | "eslintConfig": { 22 | "extends": "react-app" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /dockerfiles/Dockerfile-data: -------------------------------------------------------------------------------- 1 | FROM quay.io/quarkus/centos-quarkus-maven:20.1.0-java11 as quarkus-dev 2 | COPY --chown=1001:1001 quarkus-backend /quarkus-backend 3 | WORKDIR /quarkus-backend 4 | RUN env && \ 5 | mvn package && \ 6 | mvn dependency:go-offline -Dnative 7 | 8 | FROM quay.io/eclipse/che-nodejs12-community:nightly as node-frontend-dev 9 | COPY --chown=10001:10001 node-frontend /projects/quarkus-reactjs-postit-app/node-frontend 10 | WORKDIR /projects/quarkus-reactjs-postit-app/node-frontend 11 | RUN env && \ 12 | npm install && \ 13 | tar zcvf node_modules.tar.gz node_modules 14 | 15 | FROM registry.access.redhat.com/ubi8/ubi 16 | COPY --from=quarkus-dev /home/quarkus/.m2/repository /work/m2repo 17 | COPY --from=node-frontend-dev /projects/quarkus-reactjs-postit-app/node-frontend/node_modules.tar.gz /work/node_modules.tar.gz 18 | COPY dockerfiles/data-copy.sh /data-copy.sh 19 | RUN chmod 775 /data-copy.sh 20 | CMD ["/data-copy.sh"] 21 | 22 | -------------------------------------------------------------------------------- /node-frontend/src/components/PostList.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Post from './Post' 3 | import Container from 'react-bootstrap/Container' 4 | 5 | class PostList extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | posts: null, 10 | } 11 | this.updatePosts = this.updatePosts.bind(this) 12 | } 13 | 14 | componentDidMount() { 15 | fetch('posts') 16 | .then(response => response.json()) 17 | .then(data => this.updatePosts(data)) 18 | } 19 | 20 | render() { 21 | return ( 22 | 23 | {this.getPosts()} 24 | 25 | ) 26 | } 27 | 28 | updatePosts(posts) { 29 | if (Array.isArray(posts)) { 30 | this.setState({ 31 | posts: posts 32 | }) 33 | } 34 | } 35 | 36 | getPosts() { 37 | if (this.state.posts == null) { 38 | return
waiting
39 | } else { 40 | return this.state.posts.map((post) => 41 | 42 | ) 43 | } 44 | } 45 | } 46 | 47 | export default PostList -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Cloud Ready Postit application 2 | A Cloud ready Post it app composed of 3 | - a Quarkus backend, 4 | - a Nodejs/Reactjs frontend and 5 | - a Mongodb database 6 | 7 | 8 | To run this demo: 9 | 1. Fork this repo and modify the following button changing the URL on this README.md file: 10 | 2. Start the workspace: [![Contribute](factory-contribute.svg)](https://blog.sunix.org/factory?url=https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app) 11 | 12 | The URL should use your instance of Che/CodeReady Workspaces: 13 | 14 | ``` 15 | https:///factory?url=https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app 16 | ``` 17 | 18 | Alternatively, 19 | 1. Add your prefered Che or CodeReady Workspaces instance: https://blog.sunix.org/factory (that would just do the right redirection to the right server based on your preferences) 20 | 2. Start the workspace: [![Contribute](factory-contribute.svg)](https://blog.sunix.org/factory?url=https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app) 21 | 22 | ![Application topology](topology.png "Application Topology") 23 | 24 | ![CodeReady Workspaces](codeready-workspaces-preview.png "CodeReady Workspaces") 25 | -------------------------------------------------------------------------------- /README-che.md: -------------------------------------------------------------------------------- 1 | # The Cloud Ready Postit application 2 | A Cloud ready Post it app composed of 3 | - a Quarkus backend, 4 | - a Nodejs/Reactjs frontend and 5 | - a Mongodb database 6 | 7 | 8 | To run this demo: 9 | 1. Fork this repo and modify the following button changing the URL on this README.md file: 10 | 2. Start the workspace: [![Contribute](https://www.eclipse.org/che/contribute.svg)](https://blog.sunix.org/factory?url=https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app/raw/master/che-devfile.yaml) 11 | 12 | The URL should use your instance of Che/CodeReady Workspaces: 13 | 14 | ``` 15 | https:///factory?url=https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app/raw/master/che-devfile.yaml 16 | ``` 17 | 18 | Alternatively, 19 | 1. Add your prefered Che or CodeReady Workspaces instance: https://blog.sunix.org/factory (that would just do the right redirection to the right server based on your preferences) 20 | 2. Start the workspace: [![Contribute](https://www.eclipse.org/che/contribute.svg)](https://blog.sunix.org/factory?url=https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app/raw/master/che-devfile.yaml) 21 | 22 | ![Application topology](topology.png "Application Topology") 23 | 24 | ![CodeReady Workspaces](codeready-workspaces-preview.png "CodeReady Workspaces") 25 | -------------------------------------------------------------------------------- /quarkus-backend/src/main/java/org/eclipse/chedemos/Post.java: -------------------------------------------------------------------------------- 1 | package org.eclipse.chedemos; 2 | 3 | import java.util.Date; 4 | import java.util.Objects; 5 | 6 | import io.quarkus.mongodb.panache.MongoEntity; 7 | import io.quarkus.mongodb.panache.PanacheMongoEntity; 8 | import io.quarkus.runtime.annotations.RegisterForReflection; 9 | 10 | @RegisterForReflection 11 | @MongoEntity(collection = "Posts") 12 | public class Post extends PanacheMongoEntity { 13 | private String title; 14 | private String content; 15 | private long timestamp; 16 | 17 | public Post() { 18 | } 19 | 20 | public Post(String title, String content) { 21 | this.title = title; 22 | this.content = content; 23 | this.timestamp = new Date().getTime(); 24 | } 25 | 26 | public String getTitle() { 27 | return title; 28 | } 29 | 30 | public String getContent() { 31 | return content; 32 | } 33 | 34 | public Long getTimestamp() { 35 | return timestamp; 36 | } 37 | 38 | public void setTitle(String title) { 39 | this.title = title; 40 | } 41 | 42 | public void setContent(String content) { 43 | this.content = content; 44 | } 45 | 46 | public void setTimestamp(long timestamp) { 47 | this.timestamp = timestamp; 48 | } 49 | 50 | @Override 51 | public boolean equals(Object obj) { 52 | if (!(obj instanceof Post)) { 53 | return false; 54 | } 55 | Post other = (Post) obj; 56 | 57 | return Objects.equals(this.title, other.title) && Objects.equals(this.content, other.content) 58 | && Objects.equals(this.timestamp, other.timestamp); 59 | } 60 | 61 | @Override 62 | public int hashCode() { 63 | return Objects.hash(this.title, this.content, this.timestamp); 64 | } 65 | } -------------------------------------------------------------------------------- /node-frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 17 | 18 | 22 | 23 | 32 | React App 33 | 34 | 35 | 36 |
37 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /package-local.devfile.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1.0.0 2 | metadata: 3 | generateName: package-local-postit-app- 4 | 5 | projects: 6 | 7 | - source: 8 | type: git 9 | location: 'https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app' 10 | name: postit-app 11 | 12 | components: 13 | 14 | - alias: quarkus-backend-dev 15 | type: dockerimage 16 | image: quay.io/quarkus/centos-quarkus-maven:19.2.1 17 | memoryLimit: 1Gi 18 | command: ['sleep'] 19 | args: ['infinity'] 20 | mountSources: true 21 | env: 22 | - name: MAVEN_OPTS 23 | value: '-Dmaven.repo.local=/projects/local/m2repo' 24 | 25 | - alias: node-frontend-dev 26 | mountSources: true 27 | image: 'quay.io/eclipse/che-nodejs8-centos:7.2.0' 28 | memoryLimit: 768Mi 29 | type: dockerimage 30 | 31 | - alias: git 32 | type: dockerimage 33 | image: sunix/git-devtools 34 | mountSources: true 35 | memoryLimit: 512M 36 | args: ['sleep', 'infinity'] 37 | 38 | commands: 39 | 40 | - name: prepare local quarkus-backend 41 | actions: 42 | - type: exec 43 | command: |- 44 | mkdir -p /projects/local/m2repo; 45 | rm /projects/local/m2repo/* -rf ; 46 | mvn package; 47 | component: quarkus-backend-dev 48 | workdir: /projects/postit-app/quarkus-backend 49 | 50 | 51 | - name: prepare local node_modules 52 | actions: 53 | - type: exec 54 | command: |- 55 | mkdir -p /projects/local; 56 | rm /projects/local/node_modules.tar.gz -rf; 57 | rm /projects/postit-app/node-frontend/node_modules -rf; 58 | npm install; 59 | tar -zcvf /projects/local/node_modules.tar.gz node_modules; 60 | component: node-frontend-dev 61 | workdir: /projects/postit-app/node-frontend/ 62 | 63 | 64 | 65 | - name: zip everything 66 | actions: 67 | - type: exec 68 | command: |- 69 | rm local.zip; 70 | zip -r local.zip *; 71 | component: git 72 | workdir: /projects/local/ -------------------------------------------------------------------------------- /node-frontend/src/components/Post.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Row from 'react-bootstrap/Row' 3 | import Col from 'react-bootstrap/Col' 4 | import Container from 'react-bootstrap/Container' 5 | import Button from 'react-bootstrap/Button'; 6 | 7 | 8 | class Post extends React.Component { 9 | constructor(props) { 10 | super(props); 11 | this.state = { 12 | id: this.props.id, 13 | title: this.props.title, 14 | content: this.props.content, 15 | timestamp: this.props.timestamp, 16 | } 17 | this.deletePost = this.deletePost.bind(this); 18 | } 19 | 20 | render() { 21 | return ( 22 | 23 | 24 | 25 | {this.state.title} 26 | 27 | 28 | 29 | 30 | {this.state.content} 31 | 32 | 33 | 34 | 35 | {this.getDate(this.state.timestamp)} 36 | 37 | 38 | 41 | 42 | 43 | 44 | ) 45 | } 46 | getDate(epoch) { 47 | var d = new Date(epoch); 48 | return "Posted at " + d.toLocaleTimeString() + " on " + d.toLocaleDateString() 49 | } 50 | 51 | deletePost() { 52 | fetch('posts', { 53 | method: 'DELETE', 54 | body: JSON.stringify(this.state), 55 | headers: { 56 | 'Content-Type': 'application/json' 57 | } 58 | }) 59 | .then(response => response.json()) 60 | .then(data => console.log(data)) 61 | .catch(error => console.log(error)) 62 | window.location.reload(); 63 | } 64 | 65 | } 66 | 67 | export default Post -------------------------------------------------------------------------------- /node-frontend/src/components/PostInput.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Form from 'react-bootstrap/Form' 3 | import Container from 'react-bootstrap/Container' 4 | import Button from 'react-bootstrap/Button' 5 | import Alert from 'react-bootstrap/Alert' 6 | 7 | class PostInput extends React.Component { 8 | constructor(props) { 9 | super(props); 10 | this.state = { 11 | post: { 12 | title: "", 13 | content: "", 14 | timestamp: 0, 15 | }, 16 | submitError: false, 17 | }; 18 | 19 | this.handleTitleChange = this.handleTitleChange.bind(this); 20 | this.handleContentChange = this.handleContentChange.bind(this); 21 | this.handleSubmit = this.handleSubmit.bind(this); 22 | } 23 | 24 | handleTitleChange(event) { 25 | this.setState({ 26 | post: Object.assign({}, this.state.post, {title: event.target.value}) 27 | }); 28 | } 29 | 30 | handleContentChange(event) { 31 | this.setState({ 32 | post: Object.assign({}, this.state.post, {content: event.target.value}) 33 | }); 34 | } 35 | 36 | handleSubmit(event) { 37 | var now = Date.now(); 38 | fetch('posts', { 39 | method: 'POST', 40 | body: JSON.stringify(Object.assign({}, this.state.post, {timestamp: now})), 41 | headers: { 42 | 'Content-Type': 'application/json' 43 | } 44 | }) 45 | .then(response => { 46 | if (response.status !== 200) { 47 | this.setState({submitError: response.status}) 48 | return; 49 | } 50 | 51 | response.json().then(data => console.log("Recieved response:" + data)); 52 | window.location.reload() 53 | }) 54 | .catch(error => console.log(error)); 55 | event.preventDefault(); 56 | } 57 | 58 | handleErrorAlert() { 59 | if (this.state.submitError) { 60 | return ( 61 | this.setState({submitError: false})}> 64 | Unable to submit post, received status {this.state.submitError} from server. 65 | 66 | ); 67 | } 68 | } 69 | 70 | render() { 71 | return ( 72 | 73 | {this.handleErrorAlert()} 74 |
75 | 76 | Title 77 | 82 | 83 | 84 | Content 85 | 90 | 91 | 94 |
95 |
96 | ) 97 | } 98 | } 99 | 100 | export default PostInput -------------------------------------------------------------------------------- /.che-didact-guide.md: -------------------------------------------------------------------------------- 1 | # Welcome to Postitapp workspace 2 | 3 | This guide contains the instructions to build and run the Postit app in this workspace. 4 | 5 | The guide is interactive. You can click on the below links to open files or start the predefined commands. 6 | 7 | Powered by [Eclipse Che/](https://www.eclipse.org/che/) and [VSCode Didact](https://github.com/redhat-developer/vscode-didact). 8 | 9 | Enjoy! 10 | 11 | ## Architecture 12 | A Cloud ready Post it app composed of 13 | - a Quarkus backend, 14 | - a Nodejs/Reactjs frontend and 15 | - a Mongodb database 16 | 17 | ![Application topology](https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app/raw/master/topology.png) 18 | 19 | ## Mongo database 20 | A mongo database comes with workspace. 21 | 22 | The predefined task `show posts` will run the right `mongo cli` command do display the list of posts in your database. 23 | 24 | - [Run the `show post` predefined task](didact://?commandId=workbench.action.tasks.runTask&text=show%20posts) 25 | 26 | ## Start the Quarkus backend in Dev Mode 27 | The predefined task `start DEVMODE quarkus-backend` will start the quarkus backend in Dev Mode. Once it is started, the debug mode and live reload will be available. 28 | 29 | - [Run the `start DEVMODE quarkus-backend` predefined task](didact://?commandId=workbench.action.tasks.runTask&text=start%20DEVMODE%20quarkus-backend) 30 | 31 | 32 | ## Start the React.js frontend in Dev Mode 33 | The predefined task `start DEVMODE node-frontend` will start the React.js frontend in Dev Mode. Once it is started, live reload will be available. 34 | 35 | - [Run the `start DEVMODE quarkus-backend` predefined task](didact://?commandId=workbench.action.tasks.runTask&text=start%20DEVMODE%20node-frontend) 36 | 37 | ## Change the backend Java files 38 | 39 | Open and Edit these files, observe that live reload works 40 | 41 | - [Open Posts.java](didact://?commandId=vscode.open&projectFilePath=quarkus-reactjs-postit-app%2Fquarkus-backend%2Fsrc%2Fmain%2Fjava%2Forg%2Feclipse%2Fchedemos%2FPost.java&number=2) 42 | - [Open PostInput.js](didact://?commandId=vscode.open&projectFilePath=quarkus-reactjs-postit-app%2Fnode-frontend%2Fsrc%2Fcomponents%2FPostInput.js&number=2) 43 | 44 | ## Debug the Quarkus backend 45 | Add a breakpoint and run start the debug mode by pressing `F5` or click [here](didact://?commandId=workbench.action.debug.start) 46 | 47 | 48 | ## Build and the native application 49 | The predefined task `build NATIVE quarkus-backend` will build the Quarkus native image with GraalVM. This task will run inside the `quarkus-backend-dev` container which has `Maven`, `Java` and `GraalVM` pre-installed. 50 | 51 | - [Run the `build NATIVE quarkus-backend` predefined task](didact://?commandId=workbench.action.tasks.runTask&text=build%20NATIVE%20quarkus-backend) 52 | 53 | Generation could take some time, be patient :) 54 | 55 | ## Start the Quarkus backend in Native Mode 56 | The predefined task `start NATIVE quarkus-backend` will start the quarkus backend in Native Mode. The native mode runs in a dedicated container based on `ubi-minimal` image. It contains just the needed pieces to run the native app. And startup is ... SUPERSONIC. 57 | 58 | - [Run the `start NATIVE quarkus-backend` predefined task](didact://?commandId=workbench.action.tasks.runTask&text=start%20NATIVE%20quarkus-backend) 59 | 60 | 61 | That's it -------------------------------------------------------------------------------- /quarkus-backend/src/main/resources/META-INF/resources/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | quarkus-demo - 1.0-SNAPSHOT 6 | 99 | 100 | 101 | 102 | 105 | 106 |
107 |
108 |

Congratulations, you have created a new Quarkus application.

109 | 110 |

Why do you see this?

111 | 112 |

This page is served by Quarkus. The source is in 113 | src/main/resources/META-INF/resources/index.html.

114 | 115 |

/posts endpoint:

116 | 117 | 118 | 119 |

What can I do from here?

120 | 121 |

If not already done, run the application in dev mode using: mvn compile quarkus:dev. 122 |

123 |
    124 |
  • Add REST resources, Servlets, functions and other services in src/main/java.
  • 125 |
  • Your static assets are located in src/main/resources/META-INF/resources.
  • 126 |
  • Configure your application in src/main/resources/application.properties. 127 |
  • 128 |
129 | 130 |

How do I get rid of this page?

131 |

Just delete the src/main/resources/META-INF/resources/index.html file.

132 |
133 |
134 |
135 |

Application

136 |
    137 |
  • GroupId: org.eclipse.chedemos
  • 138 |
  • ArtifactId: quarkus-demo
  • 139 |
  • Version: 1.0-SNAPSHOT
  • 140 |
  • Quarkus Version: 0.21.2
  • 141 |
142 |
143 |
144 |

Next steps

145 | 150 |
151 |
152 |
153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /quarkus-backend/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | org.eclipse.chedemos 6 | quarkus-backend 7 | 1.0.0-SNAPSHOT 8 | 9 | UTF-8 10 | true 11 | 2.22.0 12 | 1.4.2.Final 13 | UTF-8 14 | 11 15 | 3.8.1 16 | 11 17 | 18 | 19 | 20 | 21 | io.quarkus 22 | quarkus-bom 23 | ${quarkus.version} 24 | pom 25 | import 26 | 27 | 28 | 29 | 30 | 31 | io.quarkus 32 | quarkus-resteasy 33 | 34 | 35 | io.quarkus 36 | quarkus-junit5 37 | test 38 | 39 | 40 | io.rest-assured 41 | rest-assured 42 | test 43 | 44 | 45 | io.quarkus 46 | quarkus-mongodb-panache 47 | 48 | 49 | io.quarkus 50 | quarkus-resteasy-jsonb 51 | 52 | 53 | 54 | 55 | 56 | io.quarkus 57 | quarkus-maven-plugin 58 | ${quarkus.version} 59 | 60 | 61 | 62 | build 63 | 64 | 65 | 66 | 67 | 68 | maven-compiler-plugin 69 | ${compiler-plugin.version} 70 | 71 | 72 | maven-surefire-plugin 73 | ${surefire-plugin.version} 74 | 75 | 76 | org.jboss.logmanager.LogManager 77 | 78 | 79 | 80 | 81 | maven-antrun-plugin 82 | 1.7 83 | 84 | 85 | package 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | run 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | native 103 | 104 | 105 | native 106 | 107 | 108 | 109 | 110 | 111 | io.quarkus 112 | quarkus-maven-plugin 113 | ${quarkus.version} 114 | 115 | 116 | 117 | native-image 118 | 119 | 120 | true 121 | 122 | 123 | 124 | 125 | 126 | maven-failsafe-plugin 127 | ${surefire-plugin.version} 128 | 129 | 130 | 131 | integration-test 132 | verify 133 | 134 | 135 | 136 | ${project.build.directory}/${project.build.finalName}-runner 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /node-frontend/src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl) 104 | .then(response => { 105 | // Ensure service worker exists, and that we really are getting a JS file. 106 | const contentType = response.headers.get('content-type'); 107 | if ( 108 | response.status === 404 || 109 | (contentType != null && contentType.indexOf('javascript') === -1) 110 | ) { 111 | // No service worker found. Probably a different app. Reload the page. 112 | navigator.serviceWorker.ready.then(registration => { 113 | registration.unregister().then(() => { 114 | window.location.reload(); 115 | }); 116 | }); 117 | } else { 118 | // Service worker found. Proceed as normal. 119 | registerValidSW(swUrl, config); 120 | } 121 | }) 122 | .catch(() => { 123 | console.log( 124 | 'No internet connection found. App is running in offline mode.' 125 | ); 126 | }); 127 | } 128 | 129 | export function unregister() { 130 | if ('serviceWorker' in navigator) { 131 | navigator.serviceWorker.ready.then(registration => { 132 | registration.unregister(); 133 | }); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /che-devfile.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1.0.0 2 | metadata: 3 | generateName: postit-app- 4 | 5 | projects: 6 | 7 | - source: 8 | type: git 9 | location: 'https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app' 10 | name: postit-app 11 | 12 | 13 | components: 14 | 15 | - alias: quarkus-backend-dev 16 | type: dockerimage 17 | image: quay.io/quarkus/centos-quarkus-maven:20.0.0-java8 18 | memoryLimit: 5Gi 19 | command: ['sleep'] 20 | args: ['infinity'] 21 | mountSources: true 22 | env: 23 | - name: MAVEN_OPTS 24 | value: '-Dmaven.repo.local=/.m2/repository' 25 | - name: username 26 | value: 'user' 27 | - name: password 28 | value: 'password' 29 | - name: admin_password 30 | value: 'password' 31 | - name: uri 32 | value: 'mongodb://localhost' 33 | endpoints: 34 | - name: 'quarkus-dev' 35 | port: 8080 36 | volumes: 37 | - name: m2 38 | containerPath: /.m2 39 | 40 | - mountSources: true 41 | memoryLimit: 64M 42 | type: dockerimage 43 | image: quay.io/sunix/postit-app-dev-data 44 | alias: data 45 | volumes: 46 | - name: m2 47 | containerPath: /work/volumes/.m2 48 | 49 | - alias: node-frontend-dev 50 | mountSources: true 51 | image: 'quay.io/eclipse/che-nodejs8-centos:7.2.0' 52 | memoryLimit: 768Mi 53 | type: dockerimage 54 | endpoints: 55 | - name: '3000-tcp' 56 | port: 3000 57 | env: 58 | - name: FRONTEND_PORT 59 | value: '3000' 60 | 61 | - alias: quarkus-backend-native-prod 62 | type: dockerimage 63 | image: quay.io/quarkus/ubi-quarkus-native-image:19.2.0.1 64 | memoryLimit: 32M 65 | mountSources: true 66 | command: ['tail'] 67 | args: ['-f', '/dev/null'] 68 | endpoints: 69 | - name: '8080-tcp' 70 | port: 8080 71 | env: 72 | - name: username 73 | value: 'user' 74 | - name: password 75 | value: 'password' 76 | - name: admin_password 77 | value: 'password' 78 | - name: uri 79 | value: 'mongodb://localhost' 80 | 81 | - alias: mongo 82 | type: dockerimage 83 | image: centos/mongodb-34-centos7 84 | memoryLimit: 512Mi 85 | env: 86 | - name: MONGODB_USER 87 | value: user 88 | - name: MONGODB_PASSWORD 89 | value: password 90 | - name: MONGODB_DATABASE 91 | value: sampledb 92 | - name: MONGODB_ADMIN_PASSWORD 93 | value: password 94 | 95 | - id: redhat/quarkus-java11/latest 96 | type: chePlugin 97 | 98 | - id: redhat/vscode-openshift-connector/0.1.2 99 | type: chePlugin 100 | alias: vscode-openshift 101 | 102 | 103 | - alias: git 104 | type: dockerimage 105 | image: sunix/git-devtools 106 | mountSources: true 107 | memoryLimit: 64M 108 | args: ['sleep', 'infinity'] 109 | 110 | commands: 111 | 112 | - name: start DEVMODE quarkus-backend 113 | actions: 114 | - type: exec 115 | command: pkill java; mvn compile quarkus:dev 116 | component: quarkus-backend-dev 117 | workdir: /projects/postit-app/quarkus-backend 118 | 119 | # - name: build JVM quarkus-backend 120 | # actions: 121 | # - type: exec 122 | # command: pkill java; mvn package 123 | # component: quarkus-backend-dev 124 | # workdir: /projects/postit-app/quarkus-backend 125 | 126 | - name: build NATIVE quarkus-backend 127 | actions: 128 | - type: exec 129 | command: pkill java; mvn package -Pnative 130 | component: quarkus-backend-dev 131 | workdir: /projects/postit-app/quarkus-backend 132 | 133 | - name: start NATIVE quarkus-backend 134 | actions: 135 | - type: exec 136 | command: ./quarkus-backend-1.0.0-SNAPSHOT-runner -Dquarkus.http.host=0.0.0.0 137 | component: quarkus-backend-native-prod 138 | workdir: /projects/postit-app/quarkus-backend/target 139 | 140 | - name: Attach remote debugger 141 | actions: 142 | - referenceContent: | 143 | { 144 | "version": "0.2.0", 145 | "configurations": [ 146 | { 147 | "type": "java", 148 | "request": "attach", 149 | "name": "Attach to Remote Quarkus App", 150 | "hostName": "localhost", 151 | "port": 5005 152 | } 153 | ] 154 | } 155 | type: vscode-launch 156 | 157 | # - name: build PROD node-frontend 158 | # actions: 159 | # - type: exec 160 | # command: tar zxvf /projects/local/node_modules.tar.gz ; rm /projects/local/node_modules.tar.gz ; npm install 161 | # component: node-frontend-dev 162 | # workdir: /projects/postit-app/node-frontend/ 163 | 164 | - name: start DEVMODE node-frontend 165 | actions: 166 | - type: exec 167 | command: npm run devmode 168 | component: node-frontend-dev 169 | workdir: /projects/postit-app/node-frontend/ 170 | 171 | - name: start PROD node-frontend 172 | actions: 173 | - type: exec 174 | command: npm start 175 | component: node-frontend-dev 176 | workdir: /projects/postit-app/node-frontend/ 177 | 178 | 179 | - name: oc - deploy app (quarkus NATIVE) from github 180 | actions: 181 | - type: exec 182 | command: |- 183 | # mongodb 184 | oc new-app -e MONGODB_USER=user -e MONGODB_PASSWORD=password -e MONGODB_DATABASE=sampledb -e MONGODB_ADMIN_PASSWORD=password centos/mongodb-36-centos7 --name=mongo 185 | # s2i quarkus app from source 186 | oc new-app quay.io/quarkus/ubi-quarkus-native-s2i:20.0.0-java8~https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app --name=quarkus-backend --context-dir=quarkus-backend -e uri=mongodb://mongo -e username=user -e password=password 187 | # s2i node frontend from source 188 | oc new-app nodejs~https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app --context-dir=node-frontend --name=node-frontend -e PORT=8080 -e COMPONENT_QUARKUS_BACKEND_HOST=quarkus-backend 189 | oc expose svc/node-frontend 190 | # quarkus native build need more cpu and memory 191 | # wait for quakus-backend build to start and cancel it to reconfigure it 192 | for i in 1 2 3 4 5 6 7 8 9; do 193 | pods="$(oc get build -o go-template='{{range .items}}{{$bc := index .metadata.annotations "openshift.io/build-config.name"}}{{$status := index .status.phase}}{{if eq $bc "quarkus-backend"}}{{if eq $status "Running"}}{{.metadata.name}}{{"\t"}}{{.status.phase}}{{"\n"}}{{end}}{{end}}{{end}}')"; 194 | echo $pods; 195 | if [ -n "$pods" ]; then 196 | break; 197 | fi 198 | echo "Waiting for quarkus-backend build to be ready..."; 199 | sleep "2"; 200 | done 201 | oc cancel-build bc/quarkus-backend 202 | oc patch bc/quarkus-backend -p '{"spec":{"resources":{"limits":{"cpu":"6", "memory":"6Gi"}}}}' 203 | oc start-build quarkus-backend 204 | oc expose svc/quarkus-backend 205 | # logs 206 | oc logs -f bc/quarkus-backend 207 | oc logs -f bc/node-frontend 208 | echo node-frontend url http://$(oc get route node-frontend --template='{{ .spec.host }}') 209 | component: vscode-openshift 210 | workdir: /projects/postit-app/node-frontend/ 211 | 212 | - name: oc - deploy app (quarkus JVM) from github 213 | actions: 214 | - type: exec 215 | command: |- 216 | # mongodb 217 | oc new-app -e MONGODB_USER=user -e MONGODB_PASSWORD=password -e MONGODB_DATABASE=sampledb -e MONGODB_ADMIN_PASSWORD=password centos/mongodb-36-centos7 --name=mongo 218 | # s2i quarkus app from source 219 | oc new-app java~https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app --name=quarkus-backend --context-dir=quarkus-backend -e uri=mongodb://mongo -e username=user -e password=password --env=JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0" 220 | oc expose svc/quarkus-backend 221 | # s2i node frontend from source 222 | oc new-app nodejs~https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app --context-dir=node-frontend --name=node-frontend -e PORT=8080 -e COMPONENT_QUARKUS_BACKEND_HOST=quarkus-backend 223 | oc expose svc/node-frontend 224 | oc logs -f bc/quarkus-backend 225 | oc logs -f bc/node-frontend 226 | echo node-frontend url http://$(oc get route node-frontend --template='{{ .spec.host }}') 227 | component: vscode-openshift 228 | workdir: /projects/postit-app/node-frontend/ 229 | 230 | - name: oc - redeploy quarkus-backend (from local sources) 231 | actions: 232 | - type: exec 233 | command: |- 234 | oc start-build quarkus-backend --from-dir=. 235 | oc logs -f bc/quarkus-backend 236 | component: vscode-openshift 237 | workdir: /projects/postit-app/ 238 | 239 | 240 | - name: oc - redeploy node-frontend (from local sources) 241 | actions: 242 | - type: exec 243 | command: |- 244 | oc start-build node-frontend --from-dir=. 245 | oc logs -f bc/node-frontend 246 | 247 | component: vscode-openshift 248 | workdir: /projects/postit-app/ 249 | 250 | 251 | 252 | - name: oc - scale node-frontend 253 | actions: 254 | - type: exec 255 | command: |- 256 | echo "Scale node-frontend. Enter the number of desired replicas:"; 257 | read replicas; 258 | oc scale dc/node-frontend --replicas=${replicas} 259 | component: vscode-openshift 260 | workdir: /projects/postit-app/ 261 | 262 | - name: oc - scale quarkus-backend 263 | actions: 264 | - type: exec 265 | command: |- 266 | echo "Scale quarkus-frontend. Enter the number of desired replicas:"; 267 | read replicas; 268 | oc scale dc/quarkus-backend --replicas=${replicas} 269 | component: vscode-openshift 270 | workdir: /projects/postit-app/ 271 | 272 | - name: oc - get node-frontend URL 273 | actions: 274 | - type: exec 275 | command: |- 276 | echo node-frontend url http://$(oc get route node-frontend --template='{{ .spec.host }}') 277 | component: vscode-openshift 278 | workdir: /projects/postit-app/node-frontend/ 279 | 280 | 281 | 282 | 283 | 284 | 285 | - name: oc login 286 | actions: 287 | - type: exec 288 | command: |- 289 | rm oc; curl https://mirror.openshift.com/pub/openshift-v4/clients/oc/latest/linux/oc.tar.gz -s | tar zxv && ./oc login --server=${KUBERNETES_SERVICE_HOST}:443 290 | component: vscode-openshift 291 | workdir: /tmp 292 | 293 | - name: show posts 294 | actions: 295 | - workdir: /tmp 296 | type: exec 297 | command: >- 298 | mongo mongodb://user:password@localhost/sampledb --eval 299 | "printjson(db.getCollection('Posts').find().toArray())" 300 | component: mongo 301 | -------------------------------------------------------------------------------- /devfile.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1.0.0 2 | metadata: 3 | generateName: postit-app- 4 | 5 | 6 | components: 7 | 8 | # Runtime Containers 9 | - alias: mongo 10 | type: dockerimage 11 | image: centos/mongodb-34-centos7 12 | memoryLimit: 512Mi 13 | env: 14 | - name: MONGODB_USER 15 | value: user 16 | - name: MONGODB_PASSWORD 17 | value: password 18 | - name: MONGODB_DATABASE 19 | value: sampledb 20 | - name: MONGODB_ADMIN_PASSWORD 21 | value: password 22 | 23 | - type: dockerimage 24 | alias: quarkus-backend-native-prod 25 | image: 'registry.access.redhat.com/ubi8/ubi-minimal' 26 | memoryLimit: 32M 27 | mountSources: true 28 | endpoints: 29 | - name: 'quarkus-prod' 30 | port: 8080 31 | command: ['tail'] 32 | args: ['-f', '/dev/null'] 33 | env: 34 | - name: username 35 | value: 'user' 36 | - name: password 37 | value: 'password' 38 | - name: admin_password 39 | value: 'password' 40 | - name: uri 41 | value: 'mongodb://localhost' 42 | 43 | - alias: node-frontend-dev 44 | mountSources: true 45 | image: 'quay.io/eclipse/che-nodejs12-community:nightly' 46 | memoryLimit: 768Mi 47 | type: dockerimage 48 | endpoints: 49 | - name: 'node-dev' 50 | port: 3000 51 | env: 52 | - name: FRONTEND_PORT 53 | value: '3000' 54 | 55 | 56 | # Dev/build containers 57 | - alias: quarkus-backend-dev 58 | type: dockerimage 59 | image: quay.io/quarkus/centos-quarkus-maven:20.1.0-java11 60 | memoryLimit: 4Gi 61 | command: ['sleep'] 62 | args: ['infinity'] 63 | mountSources: true 64 | env: 65 | - name: MAVEN_OPTS 66 | value: '-Dmaven.repo.local=/.m2/repository' 67 | - name: username 68 | value: 'user' 69 | - name: password 70 | value: 'password' 71 | - name: admin_password 72 | value: 'password' 73 | - name: uri 74 | value: 'mongodb://localhost' 75 | endpoints: 76 | - name: 'quarkus-dev' 77 | port: 8080 78 | volumes: 79 | - name: m2 80 | containerPath: /.m2 81 | 82 | - alias: git 83 | type: dockerimage 84 | image: sunix/git-devtools 85 | mountSources: true 86 | memoryLimit: 64M 87 | args: ['sleep', 'infinity'] 88 | 89 | - mountSources: true 90 | memoryLimit: 64M 91 | type: dockerimage 92 | image: quay.io/sunix/postit-app-dev-data 93 | alias: data 94 | volumes: 95 | - name: m2 96 | containerPath: /work/volumes/.m2 97 | 98 | # Plugins 99 | - id: redhat/quarkus-java11/latest 100 | type: chePlugin 101 | 102 | - id: redhat/vscode-openshift-connector/latest 103 | type: chePlugin 104 | alias: vscode-openshift 105 | 106 | - id: vscode/typescript-language-features/latest 107 | type: chePlugin 108 | 109 | - alias: didact-plugin 110 | type: chePlugin 111 | id: redhat/vscode-didact/latest 112 | preferences: 113 | didact.openDefaultTutorialAtStartup: true 114 | che.welcome.enable: false 115 | didact.defaultUrl: /projects/quarkus-reactjs-postit-app/.che-didact-guide.md 116 | registryUrl: 'https://che-plugin-registry-main.surge.sh/v3' 117 | 118 | 119 | commands: 120 | 121 | - name: start DEVMODE quarkus-backend 122 | actions: 123 | - type: exec 124 | command: pkill java; mvn compile quarkus:dev 125 | component: quarkus-backend-dev 126 | workdir: /projects/quarkus-reactjs-postit-app/quarkus-backend 127 | 128 | # - name: build JVM quarkus-backend 129 | # actions: 130 | # - type: exec 131 | # command: pkill java; mvn package 132 | # component: quarkus-backend-dev 133 | # workdir: /projects/quarkus-reactjs-postit-app/quarkus-backend 134 | 135 | - name: build NATIVE quarkus-backend 136 | actions: 137 | - type: exec 138 | command: "pkill java; mvn package -Dnative -Dmaven.test.skip -Dquarkus.native.native-image-xmx=2G" 139 | component: quarkus-backend-dev 140 | workdir: /projects/quarkus-reactjs-postit-app/quarkus-backend 141 | 142 | - name: start NATIVE quarkus-backend 143 | actions: 144 | - type: exec 145 | command: ./quarkus-backend-1.0.0-SNAPSHOT-runner -Dquarkus.http.host=0.0.0.0 146 | component: quarkus-backend-native-prod 147 | workdir: /projects/quarkus-reactjs-postit-app/quarkus-backend/target 148 | 149 | - name: connect java debugger quarkus-backend 150 | actions: 151 | - type: vscode-launch 152 | referenceContent: | 153 | { 154 | "version": "0.2.0", 155 | "configurations": [ 156 | { 157 | "type": "java", 158 | "name": "Debug (Attach) - Remote", 159 | "request": "attach", 160 | "hostName": "localhost", 161 | "port": 5005 162 | }] 163 | } 164 | 165 | 166 | # - name: build PROD node-frontend 167 | # actions: 168 | # - type: exec 169 | # command: tar zxvf /projects/local/node_modules.tar.gz ; rm /projects/local/node_modules.tar.gz ; npm install 170 | # component: node-frontend-dev 171 | # workdir: /projects/quarkus-reactjs-postit-app/node-frontend/ 172 | 173 | - name: start DEVMODE node-frontend 174 | actions: 175 | - type: exec 176 | command: npm run devmode 177 | component: node-frontend-dev 178 | workdir: /projects/quarkus-reactjs-postit-app/node-frontend/ 179 | 180 | - name: start PROD node-frontend 181 | actions: 182 | - type: exec 183 | command: npm start 184 | component: node-frontend-dev 185 | workdir: /projects/quarkus-reactjs-postit-app/node-frontend/ 186 | 187 | 188 | - name: oc - deploy app (quarkus NATIVE) from github 189 | actions: 190 | - type: exec 191 | command: |- 192 | # mongodb 193 | oc new-app -e MONGODB_USER=user -e MONGODB_PASSWORD=password -e MONGODB_DATABASE=sampledb -e MONGODB_ADMIN_PASSWORD=password centos/mongodb-36-centos7 --name=mongo 194 | # s2i quarkus app from source 195 | oc new-app quay.io/quarkus/ubi-quarkus-native-s2i:20.0.0-java8~https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app --name=quarkus-backend --context-dir=quarkus-backend -e uri=mongodb://mongo -e username=user -e password=password 196 | # s2i node frontend from source 197 | oc new-app nodejs~https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app --context-dir=node-frontend --name=node-frontend -e PORT=8080 -e COMPONENT_QUARKUS_BACKEND_HOST=quarkus-backend 198 | oc expose svc/node-frontend 199 | # quarkus native build need more cpu and memory 200 | # wait for quakus-backend build to start and cancel it to reconfigure it 201 | for i in 1 2 3 4 5 6 7 8 9; do 202 | pods="$(oc get build -o go-template='{{range .items}}{{$bc := index .metadata.annotations "openshift.io/build-config.name"}}{{$status := index .status.phase}}{{if eq $bc "quarkus-backend"}}{{if eq $status "Running"}}{{.metadata.name}}{{"\t"}}{{.status.phase}}{{"\n"}}{{end}}{{end}}{{end}}')"; 203 | echo $pods; 204 | if [ -n "$pods" ]; then 205 | break; 206 | fi 207 | echo "Waiting for quarkus-backend build to be ready..."; 208 | sleep "2"; 209 | done 210 | oc cancel-build bc/quarkus-backend 211 | oc patch bc/quarkus-backend -p '{"spec":{"resources":{"limits":{"cpu":"6", "memory":"6Gi"}}}}' 212 | oc start-build quarkus-backend 213 | oc expose svc/quarkus-backend 214 | # labels 215 | oc label deployment mongo app.openshift.io/runtime=mongodb 216 | oc label deployment node-frontend app.openshift.io/runtime=nodejs 217 | oc label deployment quarkus-backend app.openshift.io/runtime=quarkus 218 | # logs 219 | oc logs -f bc/quarkus-backend 220 | oc logs -f bc/node-frontend 221 | echo node-frontend url http://$(oc get route node-frontend --template='{{ .spec.host }}') 222 | component: vscode-openshift 223 | workdir: /projects/quarkus-reactjs-postit-app/node-frontend/ 224 | 225 | - name: oc - deploy app (quarkus JVM) from github 226 | actions: 227 | - type: exec 228 | command: |- 229 | # mongodb 230 | oc new-app -e MONGODB_USER=user -e MONGODB_PASSWORD=password -e MONGODB_DATABASE=sampledb -e MONGODB_ADMIN_PASSWORD=password centos/mongodb-36-centos7 --name=mongo 231 | # s2i quarkus app from source 232 | oc new-app java~https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app --name=quarkus-backend --context-dir=quarkus-backend -e uri=mongodb://mongo -e username=user -e password=password --env=JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0" 233 | oc expose svc/quarkus-backend 234 | # s2i node frontend from source 235 | oc new-app nodejs~https://github.com/redhat-developer-demos/quarkus-reactjs-postit-app --context-dir=node-frontend --name=node-frontend -e PORT=8080 -e COMPONENT_QUARKUS_BACKEND_HOST=quarkus-backend 236 | oc expose svc/node-frontend 237 | # labels 238 | oc label deployment mongo app.openshift.io/runtime=mongodb 239 | oc label deployment node-frontend app.openshift.io/runtime=nodejs 240 | oc label deployment quarkus-backend app.openshift.io/runtime=quarkus 241 | # logs 242 | oc logs -f bc/quarkus-backend 243 | oc logs -f bc/node-frontend 244 | echo node-frontend url http://$(oc get route node-frontend --template='{{ .spec.host }}') 245 | component: vscode-openshift 246 | workdir: /projects/quarkus-reactjs-postit-app/node-frontend/ 247 | 248 | - name: oc - redeploy quarkus-backend (from local sources) 249 | actions: 250 | - type: exec 251 | command: |- 252 | oc start-build quarkus-backend --from-dir=. 253 | oc logs -f bc/quarkus-backend 254 | component: vscode-openshift 255 | workdir: /projects/quarkus-reactjs-postit-app/ 256 | 257 | 258 | - name: oc - redeploy node-frontend (from local sources) 259 | actions: 260 | - type: exec 261 | command: |- 262 | oc start-build node-frontend --from-dir=. 263 | oc logs -f bc/node-frontend 264 | 265 | component: vscode-openshift 266 | workdir: /projects/quarkus-reactjs-postit-app/ 267 | 268 | 269 | 270 | - name: oc - scale node-frontend 271 | actions: 272 | - type: exec 273 | command: |- 274 | echo "Scale node-frontend. Enter the number of desired replicas:"; 275 | read replicas; 276 | oc scale dc/node-frontend --replicas=${replicas} 277 | component: vscode-openshift 278 | workdir: /projects/quarkus-reactjs-postit-app/ 279 | 280 | - name: oc - scale quarkus-backend 281 | actions: 282 | - type: exec 283 | command: |- 284 | echo "Scale quarkus-frontend. Enter the number of desired replicas:"; 285 | read replicas; 286 | oc scale dc/quarkus-backend --replicas=${replicas} 287 | component: vscode-openshift 288 | workdir: /projects/quarkus-reactjs-postit-app/ 289 | 290 | - name: oc - get node-frontend URL 291 | actions: 292 | - type: exec 293 | command: |- 294 | echo node-frontend url http://$(oc get route node-frontend --template='{{ .spec.host }}') 295 | component: vscode-openshift 296 | workdir: /projects/quarkus-reactjs-postit-app/node-frontend/ 297 | 298 | 299 | 300 | 301 | 302 | 303 | - name: oc login 304 | actions: 305 | - type: exec 306 | command: |- 307 | rm oc; curl https://mirror.openshift.com/pub/openshift-v4/clients/oc/latest/linux/oc.tar.gz -s | tar zxv && ./oc login --server=${KUBERNETES_SERVICE_HOST}:443 308 | component: vscode-openshift 309 | workdir: /tmp 310 | 311 | - name: show posts 312 | actions: 313 | - workdir: /tmp 314 | type: exec 315 | command: >- 316 | mongo mongodb://user:password@localhost/sampledb --eval 317 | "printjson(db.getCollection('Posts').find().toArray())" 318 | component: mongo 319 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Eclipse Public License - v 2.0 2 | 3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE 4 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION 5 | OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 6 | 7 | 1. DEFINITIONS 8 | 9 | "Contribution" means: 10 | 11 | a) in the case of the initial Contributor, the initial content 12 | Distributed under this Agreement, and 13 | 14 | b) in the case of each subsequent Contributor: 15 | i) changes to the Program, and 16 | ii) additions to the Program; 17 | where such changes and/or additions to the Program originate from 18 | and are Distributed by that particular Contributor. A Contribution 19 | "originates" from a Contributor if it was added to the Program by 20 | such Contributor itself or anyone acting on such Contributor's behalf. 21 | Contributions do not include changes or additions to the Program that 22 | are not Modified Works. 23 | 24 | "Contributor" means any person or entity that Distributes the Program. 25 | 26 | "Licensed Patents" mean patent claims licensable by a Contributor which 27 | are necessarily infringed by the use or sale of its Contribution alone 28 | or when combined with the Program. 29 | 30 | "Program" means the Contributions Distributed in accordance with this 31 | Agreement. 32 | 33 | "Recipient" means anyone who receives the Program under this Agreement 34 | or any Secondary License (as applicable), including Contributors. 35 | 36 | "Derivative Works" shall mean any work, whether in Source Code or other 37 | form, that is based on (or derived from) the Program and for which the 38 | editorial revisions, annotations, elaborations, or other modifications 39 | represent, as a whole, an original work of authorship. 40 | 41 | "Modified Works" shall mean any work in Source Code or other form that 42 | results from an addition to, deletion from, or modification of the 43 | contents of the Program, including, for purposes of clarity any new file 44 | in Source Code form that contains any contents of the Program. Modified 45 | Works shall not include works that contain only declarations, 46 | interfaces, types, classes, structures, or files of the Program solely 47 | in each case in order to link to, bind by name, or subclass the Program 48 | or Modified Works thereof. 49 | 50 | "Distribute" means the acts of a) distributing or b) making available 51 | in any manner that enables the transfer of a copy. 52 | 53 | "Source Code" means the form of a Program preferred for making 54 | modifications, including but not limited to software source code, 55 | documentation source, and configuration files. 56 | 57 | "Secondary License" means either the GNU General Public License, 58 | Version 2.0, or any later versions of that license, including any 59 | exceptions or additional permissions as identified by the initial 60 | Contributor. 61 | 62 | 2. GRANT OF RIGHTS 63 | 64 | a) Subject to the terms of this Agreement, each Contributor hereby 65 | grants Recipient a non-exclusive, worldwide, royalty-free copyright 66 | license to reproduce, prepare Derivative Works of, publicly display, 67 | publicly perform, Distribute and sublicense the Contribution of such 68 | Contributor, if any, and such Derivative Works. 69 | 70 | b) Subject to the terms of this Agreement, each Contributor hereby 71 | grants Recipient a non-exclusive, worldwide, royalty-free patent 72 | license under Licensed Patents to make, use, sell, offer to sell, 73 | import and otherwise transfer the Contribution of such Contributor, 74 | if any, in Source Code or other form. This patent license shall 75 | apply to the combination of the Contribution and the Program if, at 76 | the time the Contribution is added by the Contributor, such addition 77 | of the Contribution causes such combination to be covered by the 78 | Licensed Patents. The patent license shall not apply to any other 79 | combinations which include the Contribution. No hardware per se is 80 | licensed hereunder. 81 | 82 | c) Recipient understands that although each Contributor grants the 83 | licenses to its Contributions set forth herein, no assurances are 84 | provided by any Contributor that the Program does not infringe the 85 | patent or other intellectual property rights of any other entity. 86 | Each Contributor disclaims any liability to Recipient for claims 87 | brought by any other entity based on infringement of intellectual 88 | property rights or otherwise. As a condition to exercising the 89 | rights and licenses granted hereunder, each Recipient hereby 90 | assumes sole responsibility to secure any other intellectual 91 | property rights needed, if any. For example, if a third party 92 | patent license is required to allow Recipient to Distribute the 93 | Program, it is Recipient's responsibility to acquire that license 94 | before distributing the Program. 95 | 96 | d) Each Contributor represents that to its knowledge it has 97 | sufficient copyright rights in its Contribution, if any, to grant 98 | the copyright license set forth in this Agreement. 99 | 100 | e) Notwithstanding the terms of any Secondary License, no 101 | Contributor makes additional grants to any Recipient (other than 102 | those set forth in this Agreement) as a result of such Recipient's 103 | receipt of the Program under the terms of a Secondary License 104 | (if permitted under the terms of Section 3). 105 | 106 | 3. REQUIREMENTS 107 | 108 | 3.1 If a Contributor Distributes the Program in any form, then: 109 | 110 | a) the Program must also be made available as Source Code, in 111 | accordance with section 3.2, and the Contributor must accompany 112 | the Program with a statement that the Source Code for the Program 113 | is available under this Agreement, and informs Recipients how to 114 | obtain it in a reasonable manner on or through a medium customarily 115 | used for software exchange; and 116 | 117 | b) the Contributor may Distribute the Program under a license 118 | different than this Agreement, provided that such license: 119 | i) effectively disclaims on behalf of all other Contributors all 120 | warranties and conditions, express and implied, including 121 | warranties or conditions of title and non-infringement, and 122 | implied warranties or conditions of merchantability and fitness 123 | for a particular purpose; 124 | 125 | ii) effectively excludes on behalf of all other Contributors all 126 | liability for damages, including direct, indirect, special, 127 | incidental and consequential damages, such as lost profits; 128 | 129 | iii) does not attempt to limit or alter the recipients' rights 130 | in the Source Code under section 3.2; and 131 | 132 | iv) requires any subsequent distribution of the Program by any 133 | party to be under a license that satisfies the requirements 134 | of this section 3. 135 | 136 | 3.2 When the Program is Distributed as Source Code: 137 | 138 | a) it must be made available under this Agreement, or if the 139 | Program (i) is combined with other material in a separate file or 140 | files made available under a Secondary License, and (ii) the initial 141 | Contributor attached to the Source Code the notice described in 142 | Exhibit A of this Agreement, then the Program may be made available 143 | under the terms of such Secondary Licenses, and 144 | 145 | b) a copy of this Agreement must be included with each copy of 146 | the Program. 147 | 148 | 3.3 Contributors may not remove or alter any copyright, patent, 149 | trademark, attribution notices, disclaimers of warranty, or limitations 150 | of liability ("notices") contained within the Program from any copy of 151 | the Program which they Distribute, provided that Contributors may add 152 | their own appropriate notices. 153 | 154 | 4. COMMERCIAL DISTRIBUTION 155 | 156 | Commercial distributors of software may accept certain responsibilities 157 | with respect to end users, business partners and the like. While this 158 | license is intended to facilitate the commercial use of the Program, 159 | the Contributor who includes the Program in a commercial product 160 | offering should do so in a manner which does not create potential 161 | liability for other Contributors. Therefore, if a Contributor includes 162 | the Program in a commercial product offering, such Contributor 163 | ("Commercial Contributor") hereby agrees to defend and indemnify every 164 | other Contributor ("Indemnified Contributor") against any losses, 165 | damages and costs (collectively "Losses") arising from claims, lawsuits 166 | and other legal actions brought by a third party against the Indemnified 167 | Contributor to the extent caused by the acts or omissions of such 168 | Commercial Contributor in connection with its distribution of the Program 169 | in a commercial product offering. The obligations in this section do not 170 | apply to any claims or Losses relating to any actual or alleged 171 | intellectual property infringement. In order to qualify, an Indemnified 172 | Contributor must: a) promptly notify the Commercial Contributor in 173 | writing of such claim, and b) allow the Commercial Contributor to control, 174 | and cooperate with the Commercial Contributor in, the defense and any 175 | related settlement negotiations. The Indemnified Contributor may 176 | participate in any such claim at its own expense. 177 | 178 | For example, a Contributor might include the Program in a commercial 179 | product offering, Product X. That Contributor is then a Commercial 180 | Contributor. If that Commercial Contributor then makes performance 181 | claims, or offers warranties related to Product X, those performance 182 | claims and warranties are such Commercial Contributor's responsibility 183 | alone. Under this section, the Commercial Contributor would have to 184 | defend claims against the other Contributors related to those performance 185 | claims and warranties, and if a court requires any other Contributor to 186 | pay any damages as a result, the Commercial Contributor must pay 187 | those damages. 188 | 189 | 5. NO WARRANTY 190 | 191 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT 192 | PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" 193 | BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 194 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF 195 | TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 196 | PURPOSE. Each Recipient is solely responsible for determining the 197 | appropriateness of using and distributing the Program and assumes all 198 | risks associated with its exercise of rights under this Agreement, 199 | including but not limited to the risks and costs of program errors, 200 | compliance with applicable laws, damage to or loss of data, programs 201 | or equipment, and unavailability or interruption of operations. 202 | 203 | 6. DISCLAIMER OF LIABILITY 204 | 205 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT 206 | PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS 207 | SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 208 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST 209 | PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 210 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 211 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 212 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE 213 | POSSIBILITY OF SUCH DAMAGES. 214 | 215 | 7. GENERAL 216 | 217 | If any provision of this Agreement is invalid or unenforceable under 218 | applicable law, it shall not affect the validity or enforceability of 219 | the remainder of the terms of this Agreement, and without further 220 | action by the parties hereto, such provision shall be reformed to the 221 | minimum extent necessary to make such provision valid and enforceable. 222 | 223 | If Recipient institutes patent litigation against any entity 224 | (including a cross-claim or counterclaim in a lawsuit) alleging that the 225 | Program itself (excluding combinations of the Program with other software 226 | or hardware) infringes such Recipient's patent(s), then such Recipient's 227 | rights granted under Section 2(b) shall terminate as of the date such 228 | litigation is filed. 229 | 230 | All Recipient's rights under this Agreement shall terminate if it 231 | fails to comply with any of the material terms or conditions of this 232 | Agreement and does not cure such failure in a reasonable period of 233 | time after becoming aware of such noncompliance. If all Recipient's 234 | rights under this Agreement terminate, Recipient agrees to cease use 235 | and distribution of the Program as soon as reasonably practicable. 236 | However, Recipient's obligations under this Agreement and any licenses 237 | granted by Recipient relating to the Program shall continue and survive. 238 | 239 | Everyone is permitted to copy and distribute copies of this Agreement, 240 | but in order to avoid inconsistency the Agreement is copyrighted and 241 | may only be modified in the following manner. The Agreement Steward 242 | reserves the right to publish new versions (including revisions) of 243 | this Agreement from time to time. No one other than the Agreement 244 | Steward has the right to modify this Agreement. The Eclipse Foundation 245 | is the initial Agreement Steward. The Eclipse Foundation may assign the 246 | responsibility to serve as the Agreement Steward to a suitable separate 247 | entity. Each new version of the Agreement will be given a distinguishing 248 | version number. The Program (including Contributions) may always be 249 | Distributed subject to the version of the Agreement under which it was 250 | received. In addition, after a new version of the Agreement is published, 251 | Contributor may elect to Distribute the Program (including its 252 | Contributions) under the new version. 253 | 254 | Except as expressly stated in Sections 2(a) and 2(b) above, Recipient 255 | receives no rights or licenses to the intellectual property of any 256 | Contributor under this Agreement, whether expressly, by implication, 257 | estoppel or otherwise. All rights in the Program not expressly granted 258 | under this Agreement are reserved. Nothing in this Agreement is intended 259 | to be enforceable by any entity that is not a Contributor or Recipient. 260 | No third-party beneficiary rights are created under this Agreement. 261 | 262 | Exhibit A - Form of Secondary Licenses Notice 263 | 264 | "This Source Code may also be made available under the following 265 | Secondary Licenses when the conditions for such availability set forth 266 | in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), 267 | version(s), and exceptions or additional permissions here}." 268 | 269 | Simply including a copy of this Agreement, including this Exhibit A 270 | is not sufficient to license the Source Code under Secondary Licenses. 271 | 272 | If it is not possible or desirable to put the notice in a particular 273 | file, then You may include the notice in a location (such as a LICENSE 274 | file in a relevant directory) where a recipient would be likely to 275 | look for such a notice. 276 | 277 | You may add additional accurate notices of copyright ownership. 278 | -------------------------------------------------------------------------------- /factory-contribute.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 31 | 33 | 34 | 36 | image/svg+xml 37 | 39 | 40 | 41 | 42 | 44 | 64 | 72 | 80 | 84 | 89 | 92 | 97 | 102 | 107 | 112 | 117 | 118 | 119 | --------------------------------------------------------------------------------