├── .github
├── CODEOWNERS
├── PULL_REQUEST_TEMPLATE.md
├── workflows
│ └── main.yml
└── ISSUE_TEMPLATE.md
├── dashboard
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ ├── maven-wrapper.properties
│ │ └── MavenWrapperDownloader.java
├── src
│ ├── main
│ │ ├── resources
│ │ │ ├── data.sql
│ │ │ ├── schema.sql
│ │ │ ├── logback.xml
│ │ │ ├── static
│ │ │ │ ├── index.html
│ │ │ │ └── style.css
│ │ │ ├── application.properties
│ │ │ ├── banner_custom.txt
│ │ │ ├── templates
│ │ │ │ ├── error.html
│ │ │ │ └── dashboard.html
│ │ │ └── META-INF
│ │ │ │ └── spring
│ │ │ │ ├── integration
│ │ │ │ ├── http-api.xml
│ │ │ │ ├── jdbc.xml
│ │ │ │ ├── status-monitor.xml
│ │ │ │ └── twitter.xml
│ │ │ │ └── application.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── lil
│ │ │ └── springintegration
│ │ │ ├── domain
│ │ │ ├── AppProperties.java
│ │ │ └── AppSupportStatus.java
│ │ │ ├── endpoint
│ │ │ ├── JdbcMessageTransformer.java
│ │ │ ├── AppStatusMessageHandler.java
│ │ │ └── AppStatusMessageFilter.java
│ │ │ ├── service
│ │ │ ├── CustomerAccountService.java
│ │ │ ├── StatusMonitorService.java
│ │ │ └── ViewService.java
│ │ │ ├── DashboardApplication.java
│ │ │ └── manage
│ │ │ └── DashboardManager.java
│ └── test
│ │ └── java
│ │ └── com
│ │ └── lil
│ │ └── springintegration
│ │ └── DashboardApplicationTests.java
├── pom.xml
├── mvnw.cmd
└── mvnw
├── .gitignore
├── CONTRIBUTING.md
├── NOTICE
├── CODE_CHALLENGE_02_04.MD
├── CODE_CHALLENGE_03_04.MD
├── README.md
└── LICENSE
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # Codeowners for these exercise files:
2 | # * (asterisk) deotes "all files and folders"
3 | # Example: * @producer @instructor
4 |
--------------------------------------------------------------------------------
/dashboard/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinkedInLearning/spring-spring-integration-2848253/HEAD/dashboard/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dashboard/src/main/resources/data.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO DEVICE (name, display, isUp) VALUES
2 | ('solar_1', 'House Solar', 1),
3 | ('solar_2', 'Office Solar', 0),
4 | ('store_1', 'Main Battery', 1);
--------------------------------------------------------------------------------
/dashboard/src/main/resources/schema.sql:
--------------------------------------------------------------------------------
1 | DROP TABLE IF EXISTS DEVICE;
2 |
3 | CREATE TABLE DEVICE (
4 | id INT AUTO_INCREMENT PRIMARY KEY,
5 | name VARCHAR(250) NOT NULL,
6 | display VARCHAR(250) NOT NULL,
7 | isUp BIT NOT NULL
8 | );
9 |
--------------------------------------------------------------------------------
/dashboard/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/dashboard/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Copy To Branches
2 | on:
3 | workflow_dispatch:
4 | jobs:
5 | copy-to-branches:
6 | runs-on: ubuntu-latest
7 | steps:
8 | - uses: actions/checkout@v2
9 | with:
10 | fetch-depth: 0
11 | - name: Copy To Branches Action
12 | uses: planetoftheweb/copy-to-branches@v1
13 |
--------------------------------------------------------------------------------
/dashboard/src/main/resources/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Kinetico Power Grid: Dashboard
5 |
6 |
7 |
8 |
9 | Get your dashboard here
10 |
11 |
--------------------------------------------------------------------------------
/dashboard/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | logging.level.root = WARN
2 | logging.level.com.lil=INFO
3 | spring.banner.location = classpath:banner_custom.txt
4 | server.port = 9090
5 | server.error.whitelabel.enabled=false
6 | spring.jpa.open-in-view=
7 | twitter.oauth.consumerKey=fill_me
8 | twitter.oauth.consumerSecret=fill_me
9 | twitter.oauth.accessToken=fill_me
10 | twitter.oauth.accessTokenSecret=fill_me
11 | software.build = CH.FINAL
12 |
--------------------------------------------------------------------------------
/dashboard/src/main/java/com/lil/springintegration/domain/AppProperties.java:
--------------------------------------------------------------------------------
1 | package com.lil.springintegration.domain;
2 |
3 | import java.util.Properties;
4 |
5 | public class AppProperties {
6 |
7 | private Properties runtimeProperties;
8 |
9 | public void setRuntimeProperties(Properties props) {
10 | this.runtimeProperties = props;
11 | }
12 |
13 | public Properties getRuntimeProperties() {
14 | return runtimeProperties;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/dashboard/src/main/resources/banner_custom.txt:
--------------------------------------------------------------------------------
1 | . ____ _ __ _ _
2 | /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
3 | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
4 | \\/ ___)| |_)| | | | | || (_| | ) ) ) )
5 | ' |____| .__|_| |_|_| |_\__, | / / / /
6 | =========|_|==============|___/=/_/_/_/
7 | :: Spring Boot :: (v2.3.3.RELEASE)
8 | :: Spring Integration :: (v5.3.2 RELEASE)
9 | :: LinkedIn Learning :: Course 2848253
10 | :: Spring Integration :: Kathy D. Flint
11 | =========================================
12 |
--------------------------------------------------------------------------------
/dashboard/src/main/java/com/lil/springintegration/endpoint/JdbcMessageTransformer.java:
--------------------------------------------------------------------------------
1 | package com.lil.springintegration.endpoint;
2 |
3 | import com.lil.springintegration.domain.AppSupportStatus;
4 | import org.springframework.util.LinkedCaseInsensitiveMap;
5 |
6 | import java.util.ArrayList;
7 |
8 | public class JdbcMessageTransformer {
9 |
10 | public AppSupportStatus transform(ArrayList> outList) {
11 | AppSupportStatus x = new AppSupportStatus();
12 | x.setDeviceOut(outList);
13 | return x;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | SPRING_GUIDES.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
35 | ### Misc ###
36 | *scratch*
37 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 |
2 | Contribution Agreement
3 | ======================
4 |
5 | This repository does not accept pull requests (PRs). All pull requests will be closed.
6 |
7 | However, if any contributions (through pull requests, issues, feedback or otherwise) are provided, as a contributor, you represent that the code you submit is your original work or that of your employer (in which case you represent you have the right to bind your employer). By submitting code (or otherwise providing feedback), you (and, if applicable, your employer) are licensing the submitted code (and/or feedback) to LinkedIn and the open source community subject to the BSD 2-Clause license.
8 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | Copyright 2021 LinkedIn Corporation
2 | All Rights Reserved.
3 |
4 | Licensed under the LinkedIn Learning Exercise File License (the "License").
5 | See LICENSE in the project root for license information.
6 |
7 | Please note, this project may automatically load third party code from external
8 | repositories (for example, NPM modules, Composer packages, or other dependencies).
9 | If so, such third party code may be subject to other license terms than as set
10 | forth above. In addition, such third party code may also depend on and load
11 | multiple tiers of dependencies. Please review the applicable licenses of the
12 | additional dependencies.
13 |
14 |
15 |
--------------------------------------------------------------------------------
/dashboard/src/main/java/com/lil/springintegration/endpoint/AppStatusMessageHandler.java:
--------------------------------------------------------------------------------
1 | package com.lil.springintegration.endpoint;
2 |
3 | import com.lil.springintegration.domain.AppSupportStatus;
4 | import org.springframework.integration.MessageRejectedException;
5 | import org.springframework.messaging.Message;
6 | import org.springframework.messaging.MessageHandler;
7 | import org.springframework.messaging.MessagingException;
8 |
9 | public abstract class AppStatusMessageHandler implements MessageHandler {
10 |
11 | @Override
12 | public void handleMessage(Message> message) throws MessagingException {
13 | Object payload = message.getPayload();
14 | if (payload instanceof AppSupportStatus) {
15 | receive((AppSupportStatus) payload);
16 | } else {
17 | throw new MessageRejectedException(message, "Unknown data type has been received.");
18 | }
19 | }
20 |
21 | protected abstract void receive(AppSupportStatus status);
22 |
23 | }
24 |
25 |
26 |
--------------------------------------------------------------------------------
/dashboard/src/main/java/com/lil/springintegration/endpoint/AppStatusMessageFilter.java:
--------------------------------------------------------------------------------
1 | package com.lil.springintegration.endpoint;
2 |
3 | import com.lil.springintegration.domain.AppSupportStatus;
4 | import org.springframework.integration.MessageRejectedException;
5 | import org.springframework.integration.core.MessageSelector;
6 | import org.springframework.messaging.Message;
7 | import org.springframework.messaging.MessagingException;
8 |
9 | public abstract class AppStatusMessageFilter implements MessageSelector {
10 |
11 | @Override
12 | public boolean accept(Message> message) throws MessagingException {
13 | Object payload = message.getPayload();
14 | if (payload instanceof AppSupportStatus) {
15 | return filterMessage((AppSupportStatus) payload);
16 | } else {
17 | throw new MessageRejectedException(message, "Unknown data type has been received: " + payload.getClass());
18 | }
19 | }
20 |
21 | protected abstract boolean filterMessage(AppSupportStatus status);
22 | }
23 |
--------------------------------------------------------------------------------
/dashboard/src/main/resources/templates/error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Kinetico Power Grid: Dashboard
5 |
6 |
7 |
8 |
9 |
16 |
17 |

18 |
19 |
Something went wrong :(
20 |
Go Home
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/dashboard/src/main/java/com/lil/springintegration/service/CustomerAccountService.java:
--------------------------------------------------------------------------------
1 | package com.lil.springintegration.service;
2 |
3 | import com.lil.springintegration.domain.AppSupportStatus;
4 |
5 | public class CustomerAccountService {
6 |
7 | private static double mockPersistedCredit = 0.0;
8 |
9 | public static double getAccountCredit() { return mockPersistedCredit; }
10 |
11 | public static boolean isAccountCredit() { return mockPersistedCredit > 0; }
12 |
13 | public void creditCustomerAccount(Object payload) throws IllegalArgumentException {
14 | if (payload instanceof AppSupportStatus) {
15 | AppSupportStatus customerStatus = (AppSupportStatus) payload;
16 | if (customerStatus.getAccountCreditEarned() > 0) {
17 | // Simulates a back-end account credit
18 | mockPersistedCredit += customerStatus.getAccountCreditEarned();
19 | }
20 | } else {
21 | throw new IllegalArgumentException("Unknown data type has been received: " + payload.getClass());
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/CODE_CHALLENGE_02_04.MD:
--------------------------------------------------------------------------------
1 | # CODE CHALLENGE 02_04
2 |
3 | ## Instructions
4 |
5 | Your challenge is to change the Subscribable DirectChannel implementation that we built in 02_02 into a Subscribable PublishSubscribeChannel implementation.
6 |
7 | This way we can consume the same Channel broadcast message by two different subscribers.
8 |
9 | Start in the spring configuration file named `tech-support.xml`. On line 13 you will find instructions and a hint.
10 |
11 | Then move to these files for more instructions and hints.
12 |
13 | * ViewService.java:31
14 | * TechSupportService.java:24
15 | * DashboardManager:64
16 |
17 | (You will need to alter 4 files in total.)
18 |
19 | When you are done, start the application and open your browser to `http://localhost:9090`. In your system out console, you should see a system log message generated by TechSupportService.java:57. You should also see the current build stamp `CH.02_04` reflected in the user interface.
20 |
21 | Congrats! Thanks to the multi-broadcast capabilities of a PublishSubscribeChannel, now you have two different system responses to a single message send event.
22 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
7 |
8 | ## Issue Overview
9 |
10 |
11 | ## Describe your environment
12 |
13 |
14 | ## Steps to Reproduce
15 |
16 | 1.
17 | 2.
18 | 3.
19 | 4.
20 |
21 | ## Expected Behavior
22 |
23 |
24 | ## Current Behavior
25 |
26 |
27 | ## Possible Solution
28 |
29 |
30 | ## Screenshots / Video
31 |
32 |
33 | ## Related Issues
34 |
35 |
--------------------------------------------------------------------------------
/dashboard/src/main/resources/static/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: "Lato", sans-serif;
3 | }
4 | .logo {
5 | margin-right: 10%;
6 | float: right;
7 | width: 80px;
8 | }
9 | .h1 {
10 | float: left;
11 | color: #007089;
12 | margin-left: 20%;
13 | font-size: 120%;
14 | font-weight: bold;
15 | margin-top: 10px;
16 | margin-bottom: 10px;
17 | }
18 | .h2 {
19 | float: left;
20 | color: #8bca00;
21 | margin-left: 20%;
22 | font-size: 110%;
23 | font-style: italic;
24 | }
25 |
26 | .header {
27 | position: relative;
28 | height: 90px;
29 | }
30 |
31 | .header div {
32 | float: left;
33 | width: 60%;
34 | }
35 | .grid_shell {
36 | position: relative;
37 | width: 50%;
38 | left: 25%;
39 | padding: 10px;
40 | }
41 | .grid_row {
42 | width: 100%;
43 | height: 200px;
44 | }
45 |
46 | .grid_background {
47 | position: relative;
48 | width: 100%;
49 | overflow: hidden;
50 | }
51 |
52 | .grid_background img {
53 | position: absolute;
54 | left: 0;
55 | top: 0;
56 | width: auto;
57 | height: 400px;
58 | opacity: 0.6;
59 | }
60 |
61 | .grid_container {
62 | width: 45%;
63 | height: 170px;
64 | border: 1px dashed;
65 | border-radius: 5px;
66 | padding: 5px;
67 | background-color: #eeeeee;
68 | }
69 | .col_1 {
70 | float: left;
71 | }
72 | .col_2 {
73 | float: right;
74 | }
75 |
76 | .grid_header {
77 | color: #007089;
78 | font-size: 90%;
79 | font-weight: bold;
80 | margin-top: 5px;
81 | }
82 |
83 | .grid_body {
84 | color: #222222;
85 | font-size: 70%;
86 | }
--------------------------------------------------------------------------------
/CODE_CHALLENGE_03_04.MD:
--------------------------------------------------------------------------------
1 | # CODE CHALLENGE 03_04
2 |
3 | ## Instructions
4 |
5 | Your challenge is to add a ServiceActivator to the message flow so that our statusMonitor channel will automatically cause a customer account credit to be applied.
6 |
7 | This way the account credit functionality can be activated as a by-product of the existing message flow, without manual invocation inside our business logic.
8 |
9 | These supporting classes have been supplied
10 |
11 | * CustomerAccountService.java
12 |
13 | Your ServiceActivator should respond to messages on the statusMonitor channel. It should invoke the creditCustomerAccount() method of the CustomerAccountService class. No reply messaging is required.
14 |
15 | Start in the spring configuration file named `status-monitor.xml`. On line 24 you will find additional instructions and hints.
16 |
17 | Files you will need to alter for this challenge
18 |
19 | * status-monitor.xml
20 |
21 | To test your work, run the tests in
22 |
23 | * DashboardApplicationTests.java
24 |
25 | Once your tests are successful, start the application and open your browser to `http://localhost:9090`. In your system out console, you should see a system log message generated by CustomerAccountService.java:23. You should also see the (simulated) account credit balance accumulating in the user interface.
26 |
27 | Congrats! Thanks Spring Integration's ServiceActivator implementation, you have successfully achieved a significant business process invocation with very little development effort required. You have also practiced applying technical directives using the official Spring Integraton technical documentation.
28 |
--------------------------------------------------------------------------------
/dashboard/src/test/java/com/lil/springintegration/DashboardApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.lil.springintegration;
2 |
3 | import com.lil.springintegration.service.CustomerAccountService;
4 | import org.junit.jupiter.api.Test;
5 | import org.springframework.beans.factory.NoSuchBeanDefinitionException;
6 | import org.springframework.boot.test.context.SpringBootTest;
7 | import org.springframework.context.support.AbstractApplicationContext;
8 | import org.springframework.context.support.ClassPathXmlApplicationContext;
9 | import org.springframework.integration.channel.DirectChannel;
10 | import org.springframework.messaging.support.MessageBuilder;
11 |
12 | @SpringBootTest
13 | class DashboardApplicationTests {
14 |
15 | AbstractApplicationContext context = new ClassPathXmlApplicationContext("/META-INF/spring/application.xml", DashboardApplicationTests.class);
16 |
17 | @Test
18 | void springIntegrationContextLoads() {
19 | try {
20 | context.getBean("testMessageFlowImports");
21 | System.out.println("Spring Integration message flows imported successfully.");
22 | assert(true);
23 | } catch(NoSuchBeanDefinitionException e) {
24 | System.out.println(e.toString());
25 | assert(false);
26 | } finally {
27 | context.close();
28 | }
29 | }
30 |
31 | @Test
32 | void customerAccountServiceCreditApplied() {
33 | DirectChannel apiInputChannel = (DirectChannel) context.getBean("apiInputChannel");
34 | String apiResponse = "{\"runningVersion\":\"CH.03_03\",\"updateRequired\":true,\"netWind\":36,\"netSolar\":11,\"snapTime\":\"Fri Oct 30 12:29:26 CDT 2020\"}";
35 | assert(!CustomerAccountService.isAccountCredit());
36 | apiInputChannel.send(MessageBuilder.withPayload(apiResponse).build());
37 | assert(CustomerAccountService.isAccountCredit());
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/dashboard/src/main/java/com/lil/springintegration/service/StatusMonitorService.java:
--------------------------------------------------------------------------------
1 | package com.lil.springintegration.service;
2 |
3 | import com.lil.springintegration.endpoint.AppStatusMessageFilter;
4 | import com.lil.springintegration.endpoint.AppStatusMessageHandler;
5 | import com.lil.springintegration.manage.DashboardManager;
6 | import com.lil.springintegration.domain.AppSupportStatus;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 | import org.springframework.integration.channel.*;
10 |
11 | public class StatusMonitorService {
12 |
13 | static Logger logger = LoggerFactory.getLogger(DashboardManager.class);
14 |
15 | private AppSupportStatus currentLocalStatus;
16 |
17 | // TODO - refactor to use Spring Dependency Injection
18 | private AbstractSubscribableChannel statusMonitorChannel;
19 | private DirectChannel apiInputChannel;
20 |
21 | public StatusMonitorService() {
22 | apiInputChannel = (DirectChannel) DashboardManager.getDashboardContext().getBean("apiInputChannel");
23 | statusMonitorChannel = (PublishSubscribeChannel) DashboardManager.getDashboardContext().getBean("statusMonitorChannel");
24 | statusMonitorChannel.subscribe(new ServiceMessageHandler());
25 | }
26 |
27 | public static class ServiceMessageFilter extends AppStatusMessageFilter {
28 | protected boolean filterMessage(AppSupportStatus status) {
29 | return status.isUpdateRequired() || status.isDeviceOut();
30 | }
31 | }
32 |
33 | private class ServiceMessageHandler extends AppStatusMessageHandler {
34 | protected void receive(AppSupportStatus status) {
35 | setCurrentSupportStatus(status);
36 | }
37 | }
38 |
39 | private void setCurrentSupportStatus(AppSupportStatus status) {
40 | this.currentLocalStatus = status;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/dashboard/src/main/resources/META-INF/spring/integration/http-api.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
35 |
36 |
--------------------------------------------------------------------------------
/dashboard/src/main/resources/META-INF/spring/integration/jdbc.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/dashboard/src/main/resources/META-INF/spring/integration/status-monitor.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
29 |
30 |
31 |
32 |
33 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/dashboard/src/main/resources/META-INF/spring/integration/twitter.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
19 |
20 |
28 |
29 |
30 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/dashboard/src/main/java/com/lil/springintegration/domain/AppSupportStatus.java:
--------------------------------------------------------------------------------
1 | package com.lil.springintegration.domain;
2 |
3 | import org.springframework.util.LinkedCaseInsensitiveMap;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Date;
7 |
8 | public class AppSupportStatus {
9 |
10 | private String runningVersion;
11 | private Date snapTime = new Date();
12 | private boolean updateRequired = false;
13 | private int netSolar = 0;
14 | private int netWind = 0;
15 | private ArrayList> deviceOut = new ArrayList<>();
16 |
17 | public String getRunningVersion() {
18 | return runningVersion;
19 | }
20 | public void setRunningVersion(String version) { this.runningVersion = version; }
21 |
22 | public Date getTime() {
23 | return snapTime;
24 | }
25 | public void setTime(Date dttm) { this.snapTime = dttm; }
26 |
27 | public boolean isUpdateRequired() { return updateRequired; }
28 | public void setIsUpdateRequired(boolean update) { this.updateRequired = update; }
29 |
30 | public int getNetSolar() { return netSolar; }
31 | public void setNetSolar(int solar) { this.netSolar = solar; }
32 |
33 | public int getNetWind() { return netWind; }
34 | public void setNetWind(int wind) { this.netWind = wind; }
35 |
36 | public ArrayList> getDeviceOut() { return this.deviceOut; }
37 | public void setDeviceOut(ArrayList> out) { this.deviceOut = out; }
38 |
39 | public double getAccountCreditEarned() {
40 | return (netSolar + netWind) * .0001;
41 | }
42 |
43 | public boolean isDeviceOut() { return deviceOut.iterator().hasNext(); }
44 |
45 | public String getCustomerSoftwareNotification() {
46 | if (updateRequired) {
47 | return "A software update is required.";
48 | }
49 | return "(none)";
50 | }
51 |
52 | public String getCustomerDeviceNotification() {
53 | if (!deviceOut.isEmpty()) {
54 | return "Your power grid has one or more devices offline.";
55 | }
56 | return null;
57 | }
58 |
59 | public String toString() { return runningVersion + "@" + snapTime.toString() + (updateRequired ? "|update" : "|current") + "|" + netSolar + "|" + netWind + "|" + deviceOut.toString(); }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/dashboard/src/main/resources/META-INF/spring/application.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | ${software.build}
22 | ${server.port}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/dashboard/src/main/resources/templates/dashboard.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | kinetECO Consumer Power Grid (Spring Integration Learning Application)
5 |
6 |
7 |
8 |
9 |
16 |
17 |

18 |
19 |
20 |
21 |
22 |
Your device status.
23 |
24 |
25 |
26 |
27 |
28 |
kinetECO on Twitter.
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
Your net community grid contribution.
37 |
38 |
39 |
40 |
41 |
42 |
System support information.
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/dashboard/src/main/java/com/lil/springintegration/DashboardApplication.java:
--------------------------------------------------------------------------------
1 | package com.lil.springintegration;
2 |
3 | import com.lil.springintegration.manage.DashboardManager;
4 | import com.lil.springintegration.domain.AppProperties;
5 | import org.json.JSONException;
6 | import org.json.JSONObject;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 | import org.springframework.boot.SpringApplication;
10 | import org.springframework.boot.autoconfigure.SpringBootApplication;
11 | import org.springframework.context.support.AbstractApplicationContext;
12 | import org.springframework.context.support.ClassPathXmlApplicationContext;
13 | import org.springframework.http.HttpStatus;
14 | import org.springframework.http.ResponseEntity;
15 | import org.springframework.stereotype.Controller;
16 | import org.springframework.ui.Model;
17 | import org.springframework.web.bind.annotation.GetMapping;
18 | import org.springframework.web.bind.annotation.RequestMapping;
19 |
20 | import java.util.Date;
21 | import java.util.Random;
22 |
23 | @SpringBootApplication
24 | @Controller
25 | public class DashboardApplication {
26 |
27 | private static DashboardManager dashboardManager;
28 |
29 | private static Logger logger = LoggerFactory.getLogger(DashboardApplication.class);
30 |
31 | public static void main(String[] args) {
32 | AbstractApplicationContext context = new ClassPathXmlApplicationContext("/META-INF/spring/application.xml", DashboardApplication.class);
33 | AppProperties props = (AppProperties) context.getBean("appProperties");
34 | dashboardManager = new DashboardManager();
35 | SpringApplication.run(DashboardApplication.class, args);
36 | logger.info("Open this application in your browser at http://localhost:" + props.getRuntimeProperties().getProperty("server.port", "") + ". (Modify port number in src/main/resources/application.properties)");
37 | dashboardManager.initCallback();
38 | context.close();
39 | }
40 |
41 | @GetMapping("/")
42 | public String dashboard(Model model) {
43 | model.addAttribute("status", DashboardManager.getDashboardStatus());
44 | return "dashboard";
45 | }
46 |
47 | @RequestMapping(value = "/api")
48 | public ResponseEntity