Skip to content

Commit

Permalink
Merge pull request #37 from What-s-Your-Plan/feat/#31
Browse files Browse the repository at this point in the history
Open Weather API를 연동
  • Loading branch information
KIMSEI1124 authored Oct 17, 2024
2 parents 2bf3c0b + 3d5d12c commit 45e2a5f
Show file tree
Hide file tree
Showing 25 changed files with 644 additions and 27 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,7 @@ magick

### macOS ###
.DS_Store
/**/.DS_Store
/**/.DS_Store

### QFile ###
**/src/main/generated/**/Q*.java
6 changes: 5 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
[submodule "application/wypl-image/src/main/resources/security"]
path = application/wypl-image/src/main/resources/security
url = https://github.com/What-s-Your-Plan/wypl-image-properties.git
branch = main
branch = main
[submodule "application/wypl-core/src/main/resources/security"]
path = application/wypl-core/src/main/resources/security
url = https://github.com/What-s-Your-Plan/wypl-server-properties
branch = main
1 change: 1 addition & 0 deletions application/wypl-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ java {

dependencies {
implementation project(':application:application-common')
implementation project(':client:openweather-client')
implementation project(':domain:jpa-common')
implementation project(':domain:mongo-common')
implementation project(':domain:jpamongo-review-domain')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.wypl.wyplcore.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
33 changes: 11 additions & 22 deletions application/wypl-core/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
spring:
application:
name: wypl-core
jpa:
properties:
hibernate:
show_sql: true
format_sql: true
hibernate:
ddl-auto: create-drop
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:db
username: sa
password:
h2:
console:
enabled: true
path: /h2

de:
flapdoodle:
mongodb:
embedded:
version: 4.0.2
config:
import:
- security/application-mongo.yml
- security/application-oracle.yml
- security/application-weather.yml
activate:
on-profile:
- default
- local
- dev
- prod
1 change: 1 addition & 0 deletions application/wypl-core/src/main/resources/security
Submodule security added at 2a6e5a
55 changes: 54 additions & 1 deletion client/openweather-client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,57 @@ java {
}

dependencies {
}
implementation project(':common')

implementation('org.springframework.boot:spring-boot-starter')
implementation('org.springframework.boot:spring-boot-starter-web')

testImplementation('org.springframework.boot:spring-boot-starter-test')
testImplementation('org.mockito:mockito-core')
}

/* Jacoco Start */
tasks.withType(JacocoReport).configureEach {
reports {
html.required.set(true)
xml.required.set(true)
html.outputLocation.set(file("reports/jacoco/index.xml"))
xml.outputLocation.set(file("reports/jacoco/test/jacocoTestReport.xml"))
}

classDirectories.setFrom(
files(classDirectories.files.collect {
fileTree(it) {
exclude(
"**/config/**",
"**/data/**",
"**/exception/**",
"**/type/**",
)
}
})
)
}

tasks.jacocoTestCoverageVerification {
violationRules {
rule {
enabled = true
element = 'CLASS'

limit {
counter = 'LINE'
value = 'COVEREDRATIO'
minimum = 0.80D
}

excludes = [
"**/config/**",
"**/data/**",
"**/exception/**",
"**/type/**",
]
}
}
}
/* Jacoco End */
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.wypl.openweatherclient;

import com.wypl.openweatherclient.data.OpenWeatherCond;
import com.wypl.openweatherclient.data.OpenWeatherResponse;

public interface OpenWeatherClient {
OpenWeatherResponse fetchWeather(OpenWeatherCond cond);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.wypl.openweatherclient;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import com.wypl.openweatherclient.config.OpenWeatherProperties;
import com.wypl.openweatherclient.data.OpenWeatherCond;
import com.wypl.openweatherclient.data.OpenWeatherResponse;
import com.wypl.openweatherclient.exception.OpenWeatherErrorCode;
import com.wypl.openweatherclient.exception.OpenWeatherException;

import lombok.RequiredArgsConstructor;

@EnableConfigurationProperties(OpenWeatherProperties.class)
@RequiredArgsConstructor
@Component
public class OpenWeatherClientImpl implements OpenWeatherClient {

private final RestTemplate restTemplate;
private final OpenWeatherProperties properties;

public OpenWeatherResponse fetchWeather(OpenWeatherCond cond) {
String url = OpenWeatherUrlFactory.create(properties.getBaseUrl(), properties.getKey())
.weatherRegion(cond.city())
.isLangKr(cond.isLangKr())
.isMetric(cond.isMetric())
.build();

ResponseEntity<OpenWeatherResponse> response = restTemplate.getForEntity(
url,
OpenWeatherResponse.class
);

HttpStatusCode httpStatusCode = response.getStatusCode();
if (httpStatusCode.is2xxSuccessful()) {
return response.getBody();
}
if (httpStatusCode.is5xxServerError()) {
throw new OpenWeatherException(OpenWeatherErrorCode.INTERNAL_SERVER_ERROR);
}
throw new OpenWeatherException(OpenWeatherErrorCode.INVALID_OPEN_WEATHER_REQUEST);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.wypl.openweatherclient;

import com.wypl.openweatherclient.type.WeatherRegion;

public class OpenWeatherUrlFactory {

private final StringBuilder url;

private OpenWeatherUrlFactory(String baseUrl, String key) {
this.url = new StringBuilder(baseUrl).append("?appid=").append(key);
}

public static OpenWeatherUrlFactory create(String baseUrl, String key) {
return new OpenWeatherUrlFactory(baseUrl, key);
}

public OpenWeatherUrlFactory weatherRegion(WeatherRegion weatherRegion) {
url.append("&q=").append(weatherRegion.getCityEn());
return this;
}

public OpenWeatherUrlFactory isLangKr(boolean isLangKr) {
url.append("&lang=");
if (isLangKr) {
url.append("kr");
}
return this;
}

public OpenWeatherUrlFactory isMetric(boolean isMetric) {
url.append("&units=");
if (isMetric) {
url.append("metric");
}
return this;
}

public String build() {
return url.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.wypl.openweatherclient.config;

import org.springframework.boot.context.properties.ConfigurationProperties;

import lombok.Getter;
import lombok.Setter;

@ConfigurationProperties(prefix = "open-weather")
@Getter
@Setter
public class OpenWeatherProperties {
private String key;
private String baseUrl;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.wypl.openweatherclient.data;

import com.wypl.openweatherclient.type.WeatherRegion;

public record OpenWeatherCond(
WeatherRegion city,
boolean isMetric,
boolean isLangKr
) {
public static OpenWeatherCond fromCity(
final WeatherRegion city
) {
return new OpenWeatherCond(city, true, true);
}

public static OpenWeatherCond of(
final WeatherRegion city,
final boolean isMetric,
final boolean isLangKr
) {
return new OpenWeatherCond(city, isMetric, isLangKr);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.wypl.openweatherclient.data;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonProperty;

public record OpenWeatherResponse(
@JsonProperty("weather")
List<WeatherResponse> weather,
@JsonProperty("main")
MainResponse main,
@JsonProperty("sys")
SysResponse sys,
@JsonProperty("dt")
long dateTime
) {

public static WeatherResponse of(
final int id,
final String main,
final String desc
) {
return new WeatherResponse(id, main, desc);
}

public static MainResponse of(
final float temp,
final float maxTemp,
final float minTemp
) {
return new MainResponse(temp, maxTemp, minTemp);
}

public static SysResponse of(
final long sunrise,
final long sunset
) {
return new SysResponse(sunrise, sunset);
}

public int getWeatherId() {
return weather.get(0).id();
}

public String getWeatherName() {
return weather.get(0).main();
}

public String getWeatherDescription() {
return weather.get(0).description();
}

public float getTemperature() {
return main.temp();
}

public float getMaxTemperature() {
return main.maxTemp();
}

public float getMinTemperature() {
return main.minTemp();
}

public long getSunrise() {
return sys.sunrise();
}

public long getSunset() {
return sys.sunset();
}

public record WeatherResponse(
@JsonProperty("id")
int id,
@JsonProperty("main")
String main,
@JsonProperty("description")
String description
) {
}

public record MainResponse(
@JsonProperty("temp")
float temp,
@JsonProperty("temp_max")
float maxTemp,
@JsonProperty("temp_min")
float minTemp
) {
}

public record SysResponse(
@JsonProperty("sunrise")
long sunrise,
@JsonProperty("sunset")
long sunset
) {
}
}
Loading

0 comments on commit 45e2a5f

Please sign in to comment.