Fit for tomcat deployment
This commit is contained in:
parent
172ee3a337
commit
536218920a
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,4 +2,4 @@
|
||||
/target/
|
||||
/.idea/
|
||||
/.jpb/
|
||||
/application.properties
|
||||
/*.db
|
||||
10
application.properties
Normal file
10
application.properties
Normal file
@ -0,0 +1,10 @@
|
||||
#logging.level.de.ph87.homeautomation=DEBUG
|
||||
#-
|
||||
spring.datasource.url=jdbc:h2:./Homeautomation;AUTO_SERVER=TRUE;DB_CLOSE_ON_EXIT=FALSE
|
||||
spring.datasource.driverClassName=org.h2.Driver
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=password
|
||||
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
||||
#-
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
de.ph87.homeautomation.insert-demo-data=true
|
||||
@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd "$(dirname "$0")" || exit 1
|
||||
|
||||
mvn clean package spring-boot:repackage && \
|
||||
scp target/Homeautomation.jar media@10.0.0.50:/home/media/java/Homeautomation/Homeautomation.jar.update && \
|
||||
curl -m 2 -s http://10.0.0.50:8080/server/shutdown && echo "Server restarting..." || echo "Failed to restart server!"
|
||||
34
pom.xml
34
pom.xml
@ -7,16 +7,17 @@
|
||||
<groupId>de.ph87</groupId>
|
||||
<artifactId>Homeautomation</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>15</maven.compiler.source>
|
||||
<maven.compiler.target>15</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.3.6.RELEASE</version>
|
||||
<version>2.6.4</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
@ -28,10 +29,6 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
@ -40,15 +37,24 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.22</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@ -148,18 +154,6 @@
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<configuration>
|
||||
<mainClass>de.ph87.homeautomation.BackendApplication</mainClass>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
5
src/main/angular/.gitignore
vendored
5
src/main/angular/.gitignore
vendored
@ -1,5 +1,8 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
/node/
|
||||
|
||||
### PATRICK
|
||||
/node
|
||||
### END
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"build": "ng build --base-href /Homeautomation/",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"test": "ng test"
|
||||
},
|
||||
|
||||
@ -5,6 +5,7 @@ import {environment} from "../../environments/environment";
|
||||
import {Subject} from "rxjs";
|
||||
import {CompatClient, Stomp} from "@stomp/stompjs";
|
||||
import {Update} from "./Update";
|
||||
import {LocationStrategy} from "@angular/common";
|
||||
|
||||
export function NO_OP() {
|
||||
}
|
||||
@ -21,7 +22,7 @@ function errorInterceptor(errorHandler: (error: any) => void): ((error: any) =>
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ApiService {
|
||||
|
||||
@ -30,10 +31,12 @@ export class ApiService {
|
||||
private updateSubject = new Subject<Update<object>>();
|
||||
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
protected readonly http: HttpClient,
|
||||
protected readonly locationStrategy: LocationStrategy,
|
||||
) {
|
||||
const url = this.websocketUrl("websocket");
|
||||
this.webSocketClient = Stomp.over(function () {
|
||||
return new WebSocket(ApiService.url("ws", "websocket"));
|
||||
return new WebSocket(url);
|
||||
});
|
||||
this.webSocketClient.debug = () => null;
|
||||
this.webSocketClient.connect({}, () => {
|
||||
@ -46,27 +49,31 @@ export class ApiService {
|
||||
}
|
||||
|
||||
getItem<T>(path: string, fromJson: (json: any) => T, next: (item: T) => void = NO_OP, error: (error: any) => void = NO_OP) {
|
||||
this.http.get<any>(ApiService.url("http", path)).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
|
||||
this.http.get<any>(this.restUrl(path)).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
|
||||
}
|
||||
|
||||
getList<T>(path: string, fromJson: (json: any) => T, compare: (a: T, b: T) => number = NO_COMPARE, next: (list: T[]) => void = NO_OP, error: (error: any) => void = NO_OP) {
|
||||
this.http.get<any[]>(ApiService.url("http", path)).pipe(map(list => list.map(fromJson).sort(compare))).subscribe(next, errorInterceptor(error));
|
||||
this.http.get<any[]>(this.restUrl(path)).pipe(map(list => list.map(fromJson).sort(compare))).subscribe(next, errorInterceptor(error));
|
||||
}
|
||||
|
||||
postReturnNone<T>(path: string, data: any, next: (_: void) => void = NO_OP, error: (error: any) => void = NO_OP) {
|
||||
this.http.post<any>(ApiService.url("http", path), data).subscribe(next, errorInterceptor(error));
|
||||
this.http.post<any>(this.restUrl(path), data).subscribe(next, errorInterceptor(error));
|
||||
}
|
||||
|
||||
postReturnItem<T>(path: string, data: any, fromJson: (json: any) => T, next: (item: T) => void = NO_OP, error: (error: any) => void = NO_OP) {
|
||||
this.http.post<any>(ApiService.url("http", path), data).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
|
||||
this.http.post<any>(this.restUrl(path), data).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
|
||||
}
|
||||
|
||||
postReturnList<T>(path: string, data: any, fromJson: (json: any) => T, next: (list: T[]) => void = NO_OP, error: (error: any) => void = NO_OP) {
|
||||
this.http.post<any>(ApiService.url("http", path), data).pipe(map(list => list.map(fromJson))).subscribe(next, errorInterceptor(error));
|
||||
this.http.post<any>(this.restUrl(path), data).pipe(map(list => list.map(fromJson))).subscribe(next, errorInterceptor(error));
|
||||
}
|
||||
|
||||
private static url(schema: string, path: string): string {
|
||||
return schema + "://" + environment.host + ":" + environment.port + "/" + path;
|
||||
private restUrl(path: string): string {
|
||||
return environment.restBase + this.locationStrategy.getBaseHref() + path;
|
||||
}
|
||||
|
||||
private websocketUrl(path: string) {
|
||||
return environment.websocketBase + this.locationStrategy.getBaseHref() + path;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -3,8 +3,8 @@ import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {SearchComponent} from './search.component';
|
||||
|
||||
describe('SearchComponent', () => {
|
||||
let component: SearchComponent;
|
||||
let fixture: ComponentFixture<SearchComponent>;
|
||||
let component: SearchComponent<any>;
|
||||
let fixture: ComponentFixture<SearchComponent<any>>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
|
||||
6
src/main/angular/src/environments/UrlHelper.ts
Normal file
6
src/main/angular/src/environments/UrlHelper.ts
Normal file
@ -0,0 +1,6 @@
|
||||
const secure: boolean = window.location.protocol === "https:";
|
||||
const host: string = window.location.host.split(":", 1)[0];
|
||||
|
||||
export function getBaseUrl(protocol: string, port: number) {
|
||||
return protocol + (secure ? 's' : '') + "://" + host + ":" + port;
|
||||
}
|
||||
@ -1,5 +1,7 @@
|
||||
import {getBaseUrl} from "./UrlHelper";
|
||||
|
||||
export const environment = {
|
||||
production: true,
|
||||
host: window.location.host.split(":")[0],
|
||||
port: window.location.port,
|
||||
restBase: '',
|
||||
websocketBase: getBaseUrl('ws', parseInt(window.location.port)),
|
||||
};
|
||||
|
||||
@ -2,10 +2,12 @@
|
||||
// `ng build` replaces `environment.ts` with `environment.prod.ts`.
|
||||
// The list of file replacements can be found in `angular.json`.
|
||||
|
||||
import {getBaseUrl} from "./UrlHelper";
|
||||
|
||||
export const environment = {
|
||||
production: false,
|
||||
host: window.location.host.split(":")[0],
|
||||
port: 8080,
|
||||
restBase: getBaseUrl('http', 8080),
|
||||
websocketBase: getBaseUrl('ws', 8080),
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -1,28 +1,14 @@
|
||||
package de.ph87.homeautomation;
|
||||
|
||||
import de.ph87.homeautomation.knx.group.KnxGroupImportService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
|
||||
@SpringBootApplication
|
||||
@RequiredArgsConstructor
|
||||
public class BackendApplication {
|
||||
|
||||
private final DemoDataService demoDataService;
|
||||
|
||||
private final KnxGroupImportService knxGroupImportService;
|
||||
public class BackendApplication extends SpringBootServletInitializer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BackendApplication.class);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
knxGroupImportService.importGroups();
|
||||
demoDataService.insertDemoData();
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,6 @@ package de.ph87.homeautomation;
|
||||
|
||||
import com.luckycatlabs.sunrisesunset.Zenith;
|
||||
import de.ph87.homeautomation.channel.Channel;
|
||||
import de.ph87.homeautomation.device.DeviceRepository;
|
||||
import de.ph87.homeautomation.device.DeviceWriteService;
|
||||
import de.ph87.homeautomation.device.devices.DeviceDto;
|
||||
import de.ph87.homeautomation.knx.group.KnxGroup;
|
||||
@ -10,12 +9,10 @@ import de.ph87.homeautomation.knx.group.KnxGroupReadService;
|
||||
import de.ph87.homeautomation.logic.Logic;
|
||||
import de.ph87.homeautomation.logic.LogicOperator;
|
||||
import de.ph87.homeautomation.logic.LogicRepository;
|
||||
import de.ph87.homeautomation.logic.LogicWriter;
|
||||
import de.ph87.homeautomation.property.Property;
|
||||
import de.ph87.homeautomation.property.PropertyRepository;
|
||||
import de.ph87.homeautomation.property.PropertyType;
|
||||
import de.ph87.homeautomation.scene.SceneDto;
|
||||
import de.ph87.homeautomation.scene.SceneRepository;
|
||||
import de.ph87.homeautomation.scene.SceneWriteService;
|
||||
import de.ph87.homeautomation.schedule.Schedule;
|
||||
import de.ph87.homeautomation.schedule.ScheduleRepository;
|
||||
@ -45,17 +42,13 @@ public class DemoDataService {
|
||||
|
||||
private final DeviceWriteService deviceWriteService;
|
||||
|
||||
private final DeviceRepository deviceRepository;
|
||||
|
||||
private final PropertyRepository propertyRepository;
|
||||
|
||||
private final KnxGroupReadService knxGroupReadService;
|
||||
|
||||
private final SceneRepository sceneRepository;
|
||||
|
||||
private final SceneWriteService sceneWriteService;
|
||||
|
||||
private final LogicWriter logicWriter;
|
||||
|
||||
private final LogicRepository logicRepository;
|
||||
|
||||
@ -172,7 +165,7 @@ public class DemoDataService {
|
||||
}
|
||||
|
||||
private KnxGroup knx(final int main, final int mid, final int sub) {
|
||||
return knxGroupReadService.getByAddress(main, mid, sub);
|
||||
return knxGroupReadService.getByAddress(main, mid, sub).orElse(null);
|
||||
}
|
||||
|
||||
private Property createProperty(final String title, final PropertyType type, final Channel readChannel, final Channel writeChannel) {
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
package de.ph87.homeautomation;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("server")
|
||||
@RequiredArgsConstructor
|
||||
public class ServerController {
|
||||
|
||||
private final ServerService serverService;
|
||||
|
||||
@GetMapping("shutdown")
|
||||
public void shutdown() {
|
||||
serverService.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
package de.ph87.homeautomation;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@EnableAsync
|
||||
@RequiredArgsConstructor
|
||||
public class ServerService implements ApplicationContextAware {
|
||||
|
||||
private static final int DELAY_SECONDS = 1;
|
||||
|
||||
private ConfigurableApplicationContext applicationContext;
|
||||
|
||||
@Async
|
||||
public void shutdown() {
|
||||
try {
|
||||
for (int delay = DELAY_SECONDS; delay > 0; delay--) {
|
||||
log.info("Shutdown in {} second.", delay);
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("Shutdown interrupted.");
|
||||
return;
|
||||
}
|
||||
applicationContext.close();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
|
||||
this.applicationContext = (ConfigurableApplicationContext) ctx;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,7 @@
|
||||
package de.ph87.homeautomation.property;
|
||||
package de.ph87.homeautomation;
|
||||
|
||||
import de.ph87.homeautomation.knx.group.KnxGroupImportService;
|
||||
import de.ph87.homeautomation.property.PropertyWriteService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
@ -9,12 +11,18 @@ import org.springframework.stereotype.Service;
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PropertyEventListener {
|
||||
public class StartupService {
|
||||
|
||||
private final KnxGroupImportService knxGroupImportService;
|
||||
|
||||
private final DemoDataService demoDataService;
|
||||
|
||||
private final PropertyWriteService propertyWriteService;
|
||||
|
||||
@EventListener(ApplicationStartedEvent.class)
|
||||
public void onApplicationStarted() {
|
||||
public void startup() {
|
||||
knxGroupImportService.importGroups();
|
||||
demoDataService.insertDemoData();
|
||||
propertyWriteService.updateAllProperties();
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import tuwien.auto.calimero.GroupAddress;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ -16,8 +17,8 @@ public class KnxGroupReadService {
|
||||
|
||||
private final KnxGroupRepository knxGroupRepository;
|
||||
|
||||
public KnxGroup getByAddress(final int main, final int mid, final int sub) {
|
||||
return knxGroupRepository.findByAddressRaw(new GroupAddress(main, mid, sub).getRawAddress()).orElseThrow(RuntimeException::new);
|
||||
public Optional<KnxGroup> getByAddress(final int main, final int mid, final int sub) {
|
||||
return knxGroupRepository.findByAddressRaw(new GroupAddress(main, mid, sub).getRawAddress());
|
||||
}
|
||||
|
||||
public List<KnxGroup> findAll() {
|
||||
|
||||
@ -1,18 +1,9 @@
|
||||
package de.ph87.homeautomation.web;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.firewall.HttpFirewall;
|
||||
import org.springframework.security.web.firewall.StrictHttpFirewall;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
@ -21,34 +12,8 @@ import org.springframework.web.servlet.resource.PathResourceResolver;
|
||||
import java.io.IOException;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@RequiredArgsConstructor
|
||||
public class WebConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.cors();
|
||||
http.csrf().disable();
|
||||
http.authorizeRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) {
|
||||
web.httpFirewall(allowUrlEncodedSlashHttpFirewall());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
|
||||
final StrictHttpFirewall firewall = new StrictHttpFirewall();
|
||||
firewall.setAllowUrlEncodedSlash(true);
|
||||
firewall.setAllowSemicolon(true);
|
||||
return firewall;
|
||||
}
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
|
||||
@ -1,17 +1,10 @@
|
||||
logging.level.root=WARN
|
||||
logging.level.de.ph87=INFO
|
||||
#-
|
||||
spring.datasource.url=jdbc:h2:./Homeautomation;AUTO_SERVER=TRUE;DB_CLOSE_ON_EXIT=FALSE
|
||||
spring.datasource.driverClassName=org.h2.Driver
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=password
|
||||
#-
|
||||
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.open-in-view=false
|
||||
#-
|
||||
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
||||
#-
|
||||
spring.jackson.serialization.indent_output=true
|
||||
#-
|
||||
spring.main.banner-mode=off
|
||||
|
||||
Loading…
Reference in New Issue
Block a user