Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open Weather API를 연동 #37

Merged
merged 17 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading