<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Gradle &#8211; Ling&#039;s Note</title>
	<atom:link href="https://www.chunho-ling.com/category/computing/programming/java/gradle/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.chunho-ling.com</link>
	<description>Everything related IT, and me.</description>
	<lastBuildDate>Mon, 16 Aug 2021 07:16:30 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
<site xmlns="com-wordpress:feed-additions:1">104401516</site>	<item>
		<title>[AWS] Create file checksum file when S3 Object uploaded</title>
		<link>https://www.chunho-ling.com/aws-create-file-checksum-file-when-s3-object-uploaded/</link>
					<comments>https://www.chunho-ling.com/aws-create-file-checksum-file-when-s3-object-uploaded/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Mon, 16 Aug 2021 07:15:34 +0000</pubDate>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cloud Computing 雲端服務]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[Gradle]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Lambda Function]]></category>
		<category><![CDATA[Programming]]></category>
		<guid isPermaLink="false">https://www.chunho-ling.com/?p=1400</guid>

					<description><![CDATA[Checksum ensure the integrity of file. In AWS S3, it also using eTag to do similar things. It create MD5 value and store in eTag. However, it is not a real checksum for s3 object <a class="mh-excerpt-more" href="https://www.chunho-ling.com/aws-create-file-checksum-file-when-s3-object-uploaded/" title="[AWS] Create file checksum file when S3 Object uploaded">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>Checksum ensure the integrity of file. In AWS S3, it also using eTag to do similar things. It create MD5 value and store in eTag. However, it is not a real checksum for s3 object itself. It incudes s3 object metadata. As result, it might not the same if download file and generate checksum by own.</p>
<p>To create a real file checksum, it can be done by Lambda trigger. With lambda function, it can create trigger to execute task when file uploaded. This demo, it it will use Java to create lambda trigger to create MD5 and SHA-256 checksum.<span id="more-1400"></span></p>
<h1>Pre-requests</h1>
<ol>
<li>AWS account should has sufficient privilege to create lambda function and list s3 buckets;</li>
<li>User account for execute Lambda function should be configurated;</li>
</ol>
<h1>Steps</h1>
<ol>
<li>Create Lambda function.<br />
In AWS Management Console, click <strong>Create Function</strong>, input Function name and select Runtime to <strong>Java 11 (Corretto)</strong>, then click <strong>Create Function</strong>.<br />
<img data-recalc-dims="1" decoding="async" class="alignnone size-medium wp-image-1401" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_21_34-Window.png?resize=300%2C138&#038;ssl=1" alt="" width="300" height="138" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_21_34-Window.png?resize=300%2C138&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_21_34-Window.png?resize=1024%2C471&amp;ssl=1 1024w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_21_34-Window.png?resize=768%2C353&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_21_34-Window.png?resize=1536%2C706&amp;ssl=1 1536w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_21_34-Window.png?w=1807&amp;ssl=1 1807w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_21_34-Window.png?w=1356&amp;ssl=1 1356w" sizes="(max-width: 300px) 100vw, 300px" /></li>
<li>Add Trigger<br />
Open created trigger, click <strong>Add trigger</strong>.<br />
<img data-recalc-dims="1" decoding="async" class="alignnone size-medium wp-image-1403" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_27_37-s3-object-sha-256-Lambda-Brave.png?resize=300%2C114&#038;ssl=1" alt="" width="300" height="114" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_27_37-s3-object-sha-256-Lambda-Brave.png?resize=300%2C114&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_27_37-s3-object-sha-256-Lambda-Brave.png?w=758&amp;ssl=1 758w" sizes="(max-width: 300px) 100vw, 300px" /></li>
<li>Configure new trigger<br />
In Add trigger menu, select <strong>S3</strong> as trigger, then select target bucket in <strong>Bucket</strong> dropdown. Optionally, it can add s3 object key prefix and suffix in Prefix and suffix textbox.<br />
After tick <strong>Recursive invocation</strong> consent, click <strong>Add</strong>.<br />
<img data-recalc-dims="1" fetchpriority="high" decoding="async" class="alignnone size-medium wp-image-1402" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_26_20-Lambda-Brave.png?resize=287%2C300&#038;ssl=1" alt="" width="287" height="300" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_26_20-Lambda-Brave.png?resize=287%2C300&amp;ssl=1 287w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_26_20-Lambda-Brave.png?resize=768%2C802&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_26_20-Lambda-Brave.png?w=834&amp;ssl=1 834w" sizes="(max-width: 287px) 100vw, 287px" /></li>
<li>Create gradle library project<br />
In command prompt / terminal create project with gradle command as below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="shell">gradle init</pre>
</li>
<li>Add dependency.<br />
In build.gradle, add line below to setup dependency and build task.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="groovy">dependencies {
    implementation 'com.amazonaws:aws-lambda-java-core:1.2.1'
    implementation 'com.amazonaws:aws-lambda-java-events:3.9.0'
    runtimeOnly 'com.amazonaws:aws-lambda-java-log4j2:1.2.0'

    implementation 'software.amazon.awssdk:s3:2.17.9'

    // Use JUnit Jupiter for testing.
    testImplementation 'org.junit.jupiter:junit-jupiter:5.7.1'
}

task("buildZip", type: Zip) {
    from compileJava
    from processResources
    into("lib") {
        from configurations.runtimeClasspath
    }
}

test {
    useJUnitPlatform()
}

java {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
}

build.dependsOn buildZip
</pre>
</li>
<li>Add handler.<br />
Create new class file named GenerateChecksumEventHandler and add code below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="java">import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.core.ResponseBytes;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

public class ChecksumEventHandler implements RequestHandler&lt;S3EventNotification, Void&gt; {
    private static final String ENVIRONMENT_VARIABLE_ACCESS_KEY_ID="ACCESS_KEY_ID";
    private static final String ENVIRONMENT_VARIABLE_SECRET_ACCESS_KEY=SECRET_ACCESS_KEY";

    @Override
    public Void handleRequest(S3EventNotification input, Context context) {
        // Initial settings.
        LambdaLogger logger = context.getLogger();
        String s3AccessKeyId = System.getenv(ENVIRONMENT_VARIABLE_L2_REMOTE_ACCESS_KEY_ID);
        String s3SecretAccessKey = System.getenv(ENVIRONMENT_VARIABLE_L2_REMOTE_SECRET_ACCESS_KEY);

        // Connect to s3 with specific access key and secret access key which store in environment variable.
        AwsBasicCredentials awsCredentials = AwsBasicCredentials.create(
                s3AccessKeyId,
                s3SecretAccessKey);
        S3Client s3Client = S3Client.builder().credentialsProvider(StaticCredentialsProvider.create(awsCredentials)).build();

        // Loop with uploaded files.
        input.getRecords().forEach(o-&gt; {
            // Get related s3 object metadata and content.
            String bucketName = o.getS3().getBucket().getName();
            String objectKey = o.getS3().getObject().getKey();
            GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(bucketName).key(objectKey).build();
            ResponseBytes&lt;GetObjectResponse&gt; response = s3Client.getObjectAsBytes(getObjectRequest);
            InputStream objectByte = new ByteArrayInputStream(response.asByteArray());

            // Generate checksum file and store in same bucket.
            generateChecksumFile(logger, bucketName, objectKey, objectByte, "MD5", "md5", s3Client);
            generateChecksumFile(logger, bucketName, objectKey, objectByte, "SHA-256", "sha256", s3Client);
        });
        return null;
    }

    /**
     * Generate checksum with specific algorithm.
     * @param logger injected logger.
     * @param bucketName s3 bucket name.
     * @param objectKey s3 object key name.
     * @param inputStream s3 object input stream.
     * @param algorithm checksum algorithm required.
     * @param fileExtension checksum file extension.
     * @param s3Client injected s3 client.
     */
    private void generateChecksumFile(LambdaLogger logger, String bucketName, String objectKey, InputStream inputStream, String algorithm, String fileExtension, S3Client s3Client) {
        try {
            inputStream.reset();
            String checksum = generateChecksum(inputStream, algorithm);
            logger.log(algorithm+ " checksum = "+ checksum);
            String checksumObjectName = objectKey+ "." +fileExtension;
            RequestBody s3ObjectBody = RequestBody.fromString(checksum);
            PutObjectRequest putObjectRequest = PutObjectRequest.builder().bucket(bucketName).key(checksumObjectName).build();
            PutObjectResponse putObjectResponse = s3Client.putObject(putObjectRequest, s3ObjectBody);
            logger.log("Checksum stored and upload to bucket "+bucketName+"; path = "+ checksumObjectName+ ", e-tag = "+putObjectResponse.eTag()+".");
        } catch (NoSuchAlgorithmException | IOException e) {
            logger.log(e.getMessage());
            logger.log(Arrays.toString(e.getStackTrace()));
        }
    }

    /**
     * Generate checksum with specific algorithm.
     * @param inputStream object stream to be hash.
     * @param algorithm checksum algorithm.
     * @return Checksum in string format.
     * @throws NoSuchAlgorithmException Invalid input algorithm.
     * @throws IOException Exception when read / write byte.
     */
    private String generateChecksum(InputStream inputStream, String algorithm) throws NoSuchAlgorithmException, IOException {
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);

        DigestInputStream digestInputStream = new DigestInputStream(inputStream, messageDigest);
        byte[] buffer = new byte[4096];
        int count = 0;
        while (digestInputStream.read(buffer) &gt; -1) {
            count++;
        }
        MessageDigest digest = digestInputStream.getMessageDigest();
        digestInputStream.close();

        byte[] checksum = digest.digest();
        StringBuilder sb = new StringBuilder();
        for (byte b : checksum) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString().toUpperCase();
    }
}
</pre>
<p>As it will generate file and upload to s3 bucket, so it is required to use AWS SDK and put object permission.</li>
<li>Build distributed file.<br />
In command prompt / terminal, execute command below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="shell">gradle clean buildZip</pre>
</li>
<li>Upload file.<br />
In Lambda function, select <strong>Code</strong> tab, click <strong>Upload From</strong> &gt;<strong> zip of jar file</strong>, select built file and upload it.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1405" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_50_36-s3-object-sha-256-Lambda-Brave.png?resize=300%2C127&#038;ssl=1" alt="" width="300" height="127" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_50_36-s3-object-sha-256-Lambda-Brave.png?resize=300%2C127&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_50_36-s3-object-sha-256-Lambda-Brave.png?resize=768%2C326&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_50_36-s3-object-sha-256-Lambda-Brave.png?w=912&amp;ssl=1 912w" sizes="auto, (max-width: 300px) 100vw, 300px" /></li>
<li>Add credential.<br />
In lambda function, select <strong>Configuration</strong> &gt; <strong>Environment variables</strong>, click <strong>Edit</strong>, then add parameter below and set access key and secret key.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1404" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_47_47-Edit-environment-variables-s3-object-sha-256-Lambda-Brave.png?resize=300%2C189&#038;ssl=1" alt="" width="300" height="189" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_47_47-Edit-environment-variables-s3-object-sha-256-Lambda-Brave.png?resize=300%2C189&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_47_47-Edit-environment-variables-s3-object-sha-256-Lambda-Brave.png?resize=768%2C483&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_47_47-Edit-environment-variables-s3-object-sha-256-Lambda-Brave.png?w=845&amp;ssl=1 845w" sizes="auto, (max-width: 300px) 100vw, 300px" /></li>
<li>Create Test<br />
In lambda function, select <strong>Test</strong> tab, click <strong>new event</strong> and input event name, then input json below. Beware bucket name, arn and object key should align with triggered s3 bucket and its object.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1406" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_53_40-s3-object-sha-256-Lambda-Brave.png?resize=300%2C142&#038;ssl=1" alt="" width="300" height="142" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_53_40-s3-object-sha-256-Lambda-Brave.png?resize=300%2C142&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_53_40-s3-object-sha-256-Lambda-Brave.png?resize=1024%2C486&amp;ssl=1 1024w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_53_40-s3-object-sha-256-Lambda-Brave.png?resize=768%2C365&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_53_40-s3-object-sha-256-Lambda-Brave.png?resize=1536%2C729&amp;ssl=1 1536w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_53_40-s3-object-sha-256-Lambda-Brave.png?w=1599&amp;ssl=1 1599w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-14_53_40-s3-object-sha-256-Lambda-Brave.png?w=1356&amp;ssl=1 1356w" sizes="auto, (max-width: 300px) 100vw, 300px" /></li>
<li>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
  "Records": [
    {
      "eventVersion": "2.0",
      "eventSource": "aws:s3",
      "awsRegion": "ap-southeast-1",
      "eventTime": "1970-01-01T00:00:00.000Z",
      "eventName": "ObjectCreated:Put",
      "requestParameters": {
        "sourceIPAddress": "127.0.0.1"
      },
      "responseElements": {
        "x-amz-request-id": "EXAMPLE123456789",
        "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
      },
      "s3": {
        "bucket": {
          "name": "test-bucket",
          "arn": "arn:aws:s3:::test-bucket"
        },
        "object": {
          "key": "test.zip"
        }
      }
    }
  ]
}</pre>
</li>
<li>Execute test.<br />
Click <strong>Test</strong> to execute test, expected it will result success.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1407" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-15_00_10-s3-object-sha-256-Lambda-Brave.png?resize=300%2C133&#038;ssl=1" alt="" width="300" height="133" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-15_00_10-s3-object-sha-256-Lambda-Brave.png?resize=300%2C133&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-15_00_10-s3-object-sha-256-Lambda-Brave.png?resize=1024%2C455&amp;ssl=1 1024w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-15_00_10-s3-object-sha-256-Lambda-Brave.png?resize=768%2C341&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-15_00_10-s3-object-sha-256-Lambda-Brave.png?resize=1536%2C682&amp;ssl=1 1536w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-15_00_10-s3-object-sha-256-Lambda-Brave.png?w=1587&amp;ssl=1 1587w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2021/08/2021-08-16-15_00_10-s3-object-sha-256-Lambda-Brave.png?w=1356&amp;ssl=1 1356w" sizes="auto, (max-width: 300px) 100vw, 300px" /></li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/aws-create-file-checksum-file-when-s3-object-uploaded/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1400</post-id>	</item>
		<item>
		<title>[Java] 在Gradle project 中加入Swagger</title>
		<link>https://www.chunho-ling.com/java-%e5%9c%a8gradle-project-%e4%b8%ad%e5%8a%a0%e5%85%a5swagger/</link>
					<comments>https://www.chunho-ling.com/java-%e5%9c%a8gradle-project-%e4%b8%ad%e5%8a%a0%e5%85%a5swagger/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Wed, 15 Aug 2018 06:35:01 +0000</pubDate>
				<category><![CDATA[API Management]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[Gradle]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Swagger]]></category>
		<guid isPermaLink="false">http://www.chunho-ling.com/?p=1103</guid>

					<description><![CDATA[Swagger 是一套 Web API 管理工具, 除了一般測試外, 還可以當成API 的user menu. 而Swagger 亦已經有library 使整合變得更方便. 示範中會將swagger 整合到spring RESTful API 中. 加入dependency. 在API project 中內的 build.gradle 加入以下dependencies. dependencies { // Add Swagger. compile("io.springfox:springfox-swagger2:2.7.0") compile("io.springfox:springfox-swagger-ui:2.7.0") } 設定swagger. 於project 中建立java 檔, <a class="mh-excerpt-more" href="https://www.chunho-ling.com/java-%e5%9c%a8gradle-project-%e4%b8%ad%e5%8a%a0%e5%85%a5swagger/" title="[Java] 在Gradle project 中加入Swagger">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>Swagger 是一套 Web API 管理工具, 除了一般測試外, 還可以當成API 的user menu. 而Swagger 亦已經有library 使整合變得更方便. 示範中會將swagger 整合到spring RESTful API 中.<span id="more-1103"></span></p>
<ol>
<li>加入dependency.<br />
在API project 中內的 build.gradle 加入以下dependencies.</p>
<pre class="lang:default decode:true">dependencies {
   // Add Swagger.
   compile("io.springfox:springfox-swagger2:2.7.0")
   compile("io.springfox:springfox-swagger-ui:2.7.0")
}</pre>
</li>
<li>設定swagger.<br />
於project 中建立java 檔, 命名為SwaggerConfig.java, 並輸入以下代碼:</p>
<pre class="lang:default decode:true">import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {                                    
    @Bean
    public Docket api() { 
        return new Docket(DocumentationType.SWAGGER_2)  
          .select()                                  
          .apis(RequestHandlerSelectors.any())              
          .paths(PathSelectors.any())                          
          .build();                                           
    }
}</pre>
</li>
<li>設定與Spring 的整合.<br />
於project 中建立java 檔, 命名為SwaggerWebMvcConfigurationAdapter.java, 並輸入以下代碼:</p>
<pre class="lang:default decode:true">import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@SuppressWarnings("deprecation")
@EnableWebMvc
public class SwaggerWebMvcConfigurationAdapter extends WebMvcConfigurerAdapter {
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
	    registry.addResourceHandler("swagger-ui.html")
	      .addResourceLocations("classpath:/META-INF/resources/");
	 
	    registry.addResourceHandler("/webjars/**")
	      .addResourceLocations("classpath:/META-INF/resources/webjars/");
	}
}</pre>
</li>
<li>進行測試.<br />
執行Project, 並於瀏覽器輸入以下網址. 若見到swagger 網頁顯示, 代表測試成功.</p>
<pre class="lang:default decode:true">http://localhost:8080/swagger-ui.html</pre>
<p><img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1104" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/08/2018-08-15-14_32_10-Swagger-UI.png?resize=300%2C111&#038;ssl=1" alt="" width="300" height="111" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/08/2018-08-15-14_32_10-Swagger-UI.png?resize=300%2C111&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/08/2018-08-15-14_32_10-Swagger-UI.png?resize=768%2C283&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/08/2018-08-15-14_32_10-Swagger-UI.png?resize=1024%2C378&amp;ssl=1 1024w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/08/2018-08-15-14_32_10-Swagger-UI.png?w=1463&amp;ssl=1 1463w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/08/2018-08-15-14_32_10-Swagger-UI.png?w=1356&amp;ssl=1 1356w" sizes="auto, (max-width: 300px) 100vw, 300px" /></li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/java-%e5%9c%a8gradle-project-%e4%b8%ad%e5%8a%a0%e5%85%a5swagger/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1103</post-id>	</item>
		<item>
		<title>[Gradle] 利用profile 打包檔案</title>
		<link>https://www.chunho-ling.com/gradle-%e5%88%a9%e7%94%a8profile-%e6%89%93%e5%8c%85%e6%aa%94%e6%a1%88/</link>
					<comments>https://www.chunho-ling.com/gradle-%e5%88%a9%e7%94%a8profile-%e6%89%93%e5%8c%85%e6%aa%94%e6%a1%88/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Thu, 02 Aug 2018 08:15:20 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Gradle]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Programming]]></category>
		<guid isPermaLink="false">http://www.chunho-ling.com/?p=1087</guid>

					<description><![CDATA[進行deployment 時, 總需要於properties 檔中進行設定, 除了容易出現人為錯誤, 而且費時失事. 在Maven 中, 可以透過修改pom.xml 進行profile 設定; 而Gradle 中, 亦有同樣的設定. 建立不同的profile 檔. 於%PROJECT_HOME%/src/main/resources 中, 將原本的application.properties 複制數份, 並基於profile 命名如下. appication_&#60;&#60;ProfileName&#62;&#62;.properties 修改不同profile properties 檔設定並儲存. 設定複制設定. 於build.gradle 中加入以下代碼. processResources { def defaultProfile = 'test' <a class="mh-excerpt-more" href="https://www.chunho-ling.com/gradle-%e5%88%a9%e7%94%a8profile-%e6%89%93%e5%8c%85%e6%aa%94%e6%a1%88/" title="[Gradle] 利用profile 打包檔案">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>進行deployment 時, 總需要於properties 檔中進行設定, 除了容易出現人為錯誤, 而且費時失事. 在Maven 中, 可以透過修改pom.xml 進行profile 設定; 而Gradle 中, 亦有同樣的設定.<span id="more-1087"></span></p>
<ol>
<li>建立不同的profile 檔.<br />
於%PROJECT_HOME%/src/main/resources 中, 將原本的application.properties 複制數份, 並基於profile 命名如下.</p>
<pre class="lang:default decode:true">appication_&lt;&lt;ProfileName&gt;&gt;.properties</pre>
<p><img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1090" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/08/2018-08-02-16_00_47-eclipse-workspace-org.matilda.backend.inventory.asset_build.gradle-Eclipse-I.png?resize=261%2C176&#038;ssl=1" alt="" width="261" height="176"></li>
<li>修改不同profile properties 檔設定並儲存.</li>
<li>設定複制設定.<br />
於build.gradle 中加入以下代碼.</p>
<pre class="lang:default decode:true">processResources {
    def defaultProfile = 'test'
    def profile = (project.hasProperty('profile') ? project.profile : defaultProfile).toLowerCase()
    println 'Profile: '+profile
    include "**/application_${profile}.properties"
    rename {
        'application.properties'
    }
}</pre>
<p>在processResources() 中, 預設了test 為default profile, 若加入了profile 的話, 則會找出相對應的profile 取代原本的application.properties.</li>
<li>測試打包檔.<br />
於command prompt 中輸入以下指令:</p>
<pre class="lang:default decode:true">cd %PROJECT_DIR%
gradlew build -Pprofile &lt;&lt;ProfileName&gt;&gt;</pre>
<p>參數-P 代表parameter, profile 則是profile 設定</p>
<p><img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1088" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/08/2018-08-02-16_10_40-C__Windows_system32_cmd.exe_.png?resize=300%2C103&#038;ssl=1" alt="" width="300" height="103" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/08/2018-08-02-16_10_40-C__Windows_system32_cmd.exe_.png?resize=300%2C103&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/08/2018-08-02-16_10_40-C__Windows_system32_cmd.exe_.png?w=663&amp;ssl=1 663w" sizes="auto, (max-width: 300px) 100vw, 300px" /></li>
<li>檢查打包檔.<br />
利用解壓軟件打開打包檔, 打開WEB-INF/classes/application.properties, 若見到設定正確, 代表檔案複製成功.&nbsp;<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1089" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/08/2018-08-02-16_11_29-C__Users_chunho.ling_source_repos_org.matilda.backend.inventory.asset_build_libs.png?resize=300%2C115&#038;ssl=1" alt="" width="300" height="115" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/08/2018-08-02-16_11_29-C__Users_chunho.ling_source_repos_org.matilda.backend.inventory.asset_build_libs.png?resize=300%2C115&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/08/2018-08-02-16_11_29-C__Users_chunho.ling_source_repos_org.matilda.backend.inventory.asset_build_libs.png?w=667&amp;ssl=1 667w" sizes="auto, (max-width: 300px) 100vw, 300px" />&nbsp;</li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/gradle-%e5%88%a9%e7%94%a8profile-%e6%89%93%e5%8c%85%e6%aa%94%e6%a1%88/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1087</post-id>	</item>
		<item>
		<title>[Java] 利用Spring Data JPA 接駁 SQL server</title>
		<link>https://www.chunho-ling.com/java-%e5%88%a9%e7%94%a8spring-data-jpa-%e6%8e%a5%e9%a7%81-sql-server/</link>
					<comments>https://www.chunho-ling.com/java-%e5%88%a9%e7%94%a8spring-data-jpa-%e6%8e%a5%e9%a7%81-sql-server/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Fri, 06 Jul 2018 06:50:45 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Gradle]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Spring MVC]]></category>
		<guid isPermaLink="false">http://www.chunho-ling.com/?p=1028</guid>

					<description><![CDATA[Java Persistence API (JPA) 是 Java 內建的library 用作ORM 互動. 著名的衍生品之一就是Hibernate, 而Spring 亦基於Hibernate, 在Spring Boot 中建立了Spring Data JPA. 在示範中, 會以Gradle project 接駁SQL server 及存取資料.示範步驟如下. 加入Spring 及SQL server library. 修改Build.gradle 如下: /* * This build file was <a class="mh-excerpt-more" href="https://www.chunho-ling.com/java-%e5%88%a9%e7%94%a8spring-data-jpa-%e6%8e%a5%e9%a7%81-sql-server/" title="[Java] 利用Spring Data JPA 接駁 SQL server">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>Java Persistence API (JPA) 是 Java 內建的library 用作ORM 互動. 著名的衍生品之一就是Hibernate, 而Spring 亦基於Hibernate, 在Spring Boot 中建立了Spring Data JPA. 在示範中, 會以Gradle project 接駁SQL server 及存取資料.<span id="more-1028"></span>示範步驟如下.</p>
<ol>
<li>加入Spring 及SQL server library.<br />
修改Build.gradle 如下:</p>
<pre class="lang:default decode:true">/*
 * This build file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java Library project to get you started.
 * For more details take a look at the Java Libraries chapter in the Gradle
 * user guide available at https://docs.gradle.org/4.3/userguide/java_library_plugin.html
 */
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.3.RELEASE")
    }
}

// Apply the java-library plugin to add support for Java Library
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

// In this section you declare where to find the dependencies of your project
repositories {
    mavenCentral()
    maven { url "https://repository.jboss.org/nexus/content/repositories/releases" }
}https://www.chunho-ling.com/wp-admin/post-new.php#
sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("com.fasterxml.jackson.core:jackson-databind")
    compile("com.microsoft.sqlserver:mssql-jdbc")
    testCompile("junit:junit")
}</pre>
</li>
<li>取得library.<br />
於Project 中按右鍵並選取 <strong>Gradle</strong> &gt; <strong>Refresh Gradle Project</strong>.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1029" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/07/2018-07-06-14_25_45-eclipse-workspace-org.matilda.backend.roi_src_main_java_org_matilda_backend_ro.png?resize=222%2C300&#038;ssl=1" alt="" width="222" height="300" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/07/2018-07-06-14_25_45-eclipse-workspace-org.matilda.backend.roi_src_main_java_org_matilda_backend_ro.png?resize=222%2C300&amp;ssl=1 222w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/07/2018-07-06-14_25_45-eclipse-workspace-org.matilda.backend.roi_src_main_java_org_matilda_backend_ro.png?w=476&amp;ssl=1 476w" sizes="auto, (max-width: 222px) 100vw, 222px" /></li>
<li>設定資料庫.<br />
於/src/main/resources/ 建立檔案 application.property, 並修改內容如下.</p>
<pre class="lang:default decode:true">spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=jdbc:sqlserver://[[SQL server name]]:[[Port no.]];databaseName=[[Database name]]
spring.datasource.username=[[User name here]]
spring.datasource.password=[[Password]]</pre>
<p><strong>spring.jpa.hibernate.ddl-auto</strong> 是spring JPA 對database 的結構設定, 類似於Entity Framework 的code first. 而<strong>spring.datasource.url</strong> 指的是connection string. 會因應不同database 而有所分別.</li>
<li>建立Model.<br />
於/src/main/java/models 中建立檔案Staff.java, 並輸入以下內容.</p>
<pre class="lang:default decode:true">import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;

@Entity
public class Staff {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int StaffID;
	private String Name;
	
	public int getStaffID() {
		return StaffID;
	}

	public void setStaffID(int staffID) {
		StaffID = staffID;
	}

	public String getName() {
		return Name;
	}

	public void setName(String name) {
		Name = name;
	}
}</pre>
<p><strong>@Entity</strong> 是JPA annotation, 說明這是database entity, 若database table 與class name 不同, 則須要用@Table(name=&#8221;[[Table Name]]&#8221;) 說明. <strong>@Id</strong> 說明這是table 內的primary key, 而<strong>@GenerateValue</strong> 則說明如果建立key. 在這裡利用AUTO, 即是使用database 預設.</li>
<li>建立Repository.<br />
於/src/main/java/repositories 中建立檔案StaffRepository.java, 並輸入以下內容.</p>
<pre class="lang:default decode:true">import java.util.List;

import org.matilda.backend.roi.models.Staff;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;

public interface StaffRepository extends CrudRepository&lt;Staff, Integer&gt; {
	@Query(value="SELECT s FROM Staff s WHERE StaffID=:staffID")
	public Staff findByStaffID(@Param("staffID") int staffID);
	@Query(value="SELECT s FROM Staff s WHERE Name=:name", nativeQuery=true)
	public List&lt;Staff&gt; findByName(@Param("name") String name);
}</pre>
<p><strong>@Query</strong> 是建立Hibernate Query Language (HQL), 一種類似SQL 的query. 而<strong>@Param</strong> 則設定@Query 內的參數.</li>
<li>建立Controller.<br />
於/src/main/java/controllers 中建立檔案Staff.java, 並輸入以下內容.</p>
<pre class="lang:default decode:true">import java.util.List;

import org.matilda.backend.roi.Repositories.StaffRepository;
import org.matilda.backend.roi.models.Staff;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping(path="/main")
public class MainController {
	private static final Logger log = LoggerFactory.getLogger(MainController.class);
	@Autowired
	private StaffRepository staffRepository;
	
	@GetMapping(path="/findByStaffID")
	public @ResponseBody Staff findByStaffID(@RequestParam int staffID) {
		log.info("findByStaffID() started. staffID="+staffID);
		Staff result=staffRepository.findByStaffID(staffID);
		return result;
	}
	
	@GetMapping(path="/findByStaffName")
	public @ResponseBody List&lt;Staff&gt; findByStaffName(@RequestParam String name) {
		log.info("findByStaffName() started. name="+name);
		List&lt;Staff&gt; result=staffRepository.findByName(name);
		return result;
	}
}</pre>
<p><strong>@Controller</strong> 會在spring 中認定為controller class; <strong>@RequestMapping</strong> 設定了Controller 的root path; <strong>@Autowired</strong> 則是Spring boot 中一個DI , 將之前要設定好的bean 或compoent 叫用. <strong>@GetMapping</strong> 是@RequestMapping(method=GET) 的縮寫.</li>
<li>建立Spring Application.<br />
於/src/main/java/中建立檔案Application.java, 並輸入以下內容.</p>
<pre class="lang:default decode:true">@SpringBootApplication
public class Application {
	private static final Logger log = LoggerFactory.getLogger(Application.class);
	public static void main(String[] args) {
		log.info("Backend service ROI Starting...");
		SpringApplication.run(Application.class);
		log.info("Backend service ROI Startup completed.");
	}
}
</pre>
<p><strong>@SpringBootApplication</strong> 會執行三個annotation 的動作:</p>
<ul>
<li>@EnableAutoConfiguration: 執行 Spring Boot自動設定;</li>
<li>@ComponentScan: 搜尋所有 @Component 及inherit 的class;</li>
<li>@Configuration: 設定額外加入的 bean;</li>
</ul>
</li>
<li>執行程式.<br />
於Project 中按右鍵並選取 <strong>Debug As</strong> &gt; <strong>Spring Boot App</strong>.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1030" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/07/2018-07-06-14_26_00-eclipse-workspace-org.matilda.backend.roi_src_main_java_org_matilda_backend_ro.png?resize=274%2C300&#038;ssl=1" alt="" width="274" height="300" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/07/2018-07-06-14_26_00-eclipse-workspace-org.matilda.backend.roi_src_main_java_org_matilda_backend_ro.png?resize=274%2C300&amp;ssl=1 274w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/07/2018-07-06-14_26_00-eclipse-workspace-org.matilda.backend.roi_src_main_java_org_matilda_backend_ro.png?w=584&amp;ssl=1 584w" sizes="auto, (max-width: 274px) 100vw, 274px" /></li>
<li>測試程式.<br />
於瀏覽器中輸入 http://localhost:8080/main/findByStaffID?staffID=47 , 若有JSON 回傳, 代表結果成功.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1031" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/07/2018-07-06-14_33_46-localhost_8080_main_findByStaffID_staffID47.png?resize=300%2C158&#038;ssl=1" alt="" width="300" height="158" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/07/2018-07-06-14_33_46-localhost_8080_main_findByStaffID_staffID47.png?resize=300%2C158&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/07/2018-07-06-14_33_46-localhost_8080_main_findByStaffID_staffID47.png?w=714&amp;ssl=1 714w" sizes="auto, (max-width: 300px) 100vw, 300px" /></li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/java-%e5%88%a9%e7%94%a8spring-data-jpa-%e6%8e%a5%e9%a7%81-sql-server/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1028</post-id>	</item>
		<item>
		<title>[Java] 利用Gradle 取得SQL server driver</title>
		<link>https://www.chunho-ling.com/java-%e5%88%a9%e7%94%a8gradle-%e5%8f%96%e5%be%97sql-server-driver/</link>
					<comments>https://www.chunho-ling.com/java-%e5%88%a9%e7%94%a8gradle-%e5%8f%96%e5%be%97sql-server-driver/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Fri, 06 Jul 2018 05:44:26 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Gradle]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Programming]]></category>
		<guid isPermaLink="false">http://www.chunho-ling.com/?p=1026</guid>

					<description><![CDATA[用Java 常用的repository 通常是Maven 或 Gradle. Microsoft 除了將部份project 開源外, 還有利用Maven 做它其中一個software repository. 然而, 利用Gradle 亦有方法在Mavel 中取得有關的library. Build.gradle repositories { mavenCentral() } sourceCompatibility = 1.8 targetCompatibility = 1.8 dependencies { compile("com.microsoft.sqlserver:mssql-jdbc") } 利用mavenCentral() 可以將repository 指向Maven. 而sourceCompatibility及targetCompatibility則設定取得版本的對應Java 的版本. <a class="mh-excerpt-more" href="https://www.chunho-ling.com/java-%e5%88%a9%e7%94%a8gradle-%e5%8f%96%e5%be%97sql-server-driver/" title="[Java] 利用Gradle 取得SQL server driver">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>用Java 常用的repository 通常是Maven 或 Gradle. Microsoft 除了將部份project 開源外, 還有利用Maven 做它其中一個software repository. 然而, 利用Gradle 亦有方法在Mavel 中取得有關的library.</p>
<p><span id="more-1026"></span>Build.gradle</p>
<pre class="lang:default decode:true">repositories {
    mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile("com.microsoft.sqlserver:mssql-jdbc")
}</pre>
<p>利用<strong>mavenCentral()</strong> 可以將repository 指向Maven. 而<strong>sourceCompatibility</strong>及<strong>targetCompatibility</strong>則設定取得版本的對應Java 的版本. dependencies 則設定要叫用的library. 語法如下:</p>
<pre class="lang:default decode:true ">[[group name]]:[[package name]]: [[optional: version no]]</pre>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/java-%e5%88%a9%e7%94%a8gradle-%e5%8f%96%e5%be%97sql-server-driver/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1026</post-id>	</item>
		<item>
		<title>[Java] 利用Eclipse將 gradle project 打包做war檔</title>
		<link>https://www.chunho-ling.com/java-%e5%88%a9%e7%94%a8eclipse%e5%b0%87-gradle-project-%e6%89%93%e5%8c%85%e5%81%9awar%e6%aa%94/</link>
					<comments>https://www.chunho-ling.com/java-%e5%88%a9%e7%94%a8eclipse%e5%b0%87-gradle-project-%e6%89%93%e5%8c%85%e5%81%9awar%e6%aa%94/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Wed, 20 Jun 2018 08:53:09 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Gradle]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Spring MVC]]></category>
		<guid isPermaLink="false">http://www.chunho-ling.com/?p=1002</guid>

					<description><![CDATA[預設下Gradle 會將project 以jar 的形式打包, 然而, 若要打包的是web application的話, jar 並不能於Tomcat 或者JBoss 中發佈, 故war 檔格式雖然舊但仍有其價值. 所以須要透過plugin 去進行. (所以個人討厭寫Java 其中一個原因就是太多相類似的plugin) 加入library 及dependency. 因為spring-boot-starter-web 本身已經有tomcat container, 所以可以將之排除. 在build.gradle 中, 加入以下粗字表示的句子: buildscript { repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.3.RELEASE") <a class="mh-excerpt-more" href="https://www.chunho-ling.com/java-%e5%88%a9%e7%94%a8eclipse%e5%b0%87-gradle-project-%e6%89%93%e5%8c%85%e5%81%9awar%e6%aa%94/" title="[Java] 利用Eclipse將 gradle project 打包做war檔">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>預設下Gradle 會將project 以jar 的形式打包, 然而, 若要打包的是web application的話, jar 並不能於Tomcat 或者JBoss 中發佈, 故war 檔格式雖然舊但仍有其價值. 所以須要透過plugin 去進行. (所以個人討厭寫Java 其中一個原因就是太多相類似的plugin)<span id="more-1002"></span></p>
<ol>
<li>加入library 及dependency.<br />
因為spring-boot-starter-web 本身已經有tomcat container, 所以可以將之排除.<br />
在build.gradle 中, 加入以下<strong>粗字</strong>表示的句子:</p>
<pre class="lang:default decode:true">buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.3.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
<strong>apply plugin: 'war'</strong>

jar {
    baseName = 'gs-handling-form-submission'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    <strong>providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")</strong>
    compile("org.springframework.boot:spring-boot-starter-thymeleaf")
    testCompile("junit:junit")
}令</pre>
</li>
<li>在application.java 中, 加入以下method:
<pre class="lang:default decode:true">protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
	      return application.sources(Application.class);
	}</pre>
</li>
<li>更新Gradle project 設定, 以獲得library 及Gradle command.<br />
於project 中按右鍵 &gt;&nbsp;<strong>Gradle&nbsp;</strong>&gt;&nbsp;<strong>Refresh Gradle Project</strong>.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1004" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/06/2018-06-20-16_40_25-eclipse-workspace-org.matilda.app_src_main_java_org_matilda_app_Application.ja_.png?resize=300%2C210&#038;ssl=1" alt="" width="300" height="210" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/06/2018-06-20-16_40_25-eclipse-workspace-org.matilda.app_src_main_java_org_matilda_app_Application.ja_.png?resize=300%2C210&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/06/2018-06-20-16_40_25-eclipse-workspace-org.matilda.app_src_main_java_org_matilda_app_Application.ja_.png?resize=768%2C538&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/06/2018-06-20-16_40_25-eclipse-workspace-org.matilda.app_src_main_java_org_matilda_app_Application.ja_.png?resize=1024%2C717&amp;ssl=1 1024w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/06/2018-06-20-16_40_25-eclipse-workspace-org.matilda.app_src_main_java_org_matilda_app_Application.ja_.png?w=1062&amp;ssl=1 1062w" sizes="auto, (max-width: 300px) 100vw, 300px" /></li>
<li>建立war 檔.<br />
於Gradle Task 視窗內, 右鍵選取<strong>build</strong> &gt; <strong>Run Gradle Task</strong>.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1005" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/06/2018-06-20-16_49_00-eclipse-workspace-org.matilda.app_src_main_java_org_matilda_app_Application.ja_.png?resize=300%2C96&#038;ssl=1" alt="" width="300" height="96" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/06/2018-06-20-16_49_00-eclipse-workspace-org.matilda.app_src_main_java_org_matilda_app_Application.ja_.png?resize=300%2C96&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/06/2018-06-20-16_49_00-eclipse-workspace-org.matilda.app_src_main_java_org_matilda_app_Application.ja_.png?resize=768%2C246&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/06/2018-06-20-16_49_00-eclipse-workspace-org.matilda.app_src_main_java_org_matilda_app_Application.ja_.png?w=792&amp;ssl=1 792w" sizes="auto, (max-width: 300px) 100vw, 300px" /></li>
<li>檢查結果.&nbsp;&nbsp;<br />
執行成功的話, war 檔會放在%ProjectDir%\build\libs\ 內.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1003" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/06/2018-06-20-16_05_13-libs.png?resize=300%2C213&#038;ssl=1" alt="" width="300" height="213" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/06/2018-06-20-16_05_13-libs.png?resize=300%2C213&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/06/2018-06-20-16_05_13-libs.png?resize=768%2C546&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2018/06/2018-06-20-16_05_13-libs.png?w=890&amp;ssl=1 890w" sizes="auto, (max-width: 300px) 100vw, 300px" /></li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/java-%e5%88%a9%e7%94%a8eclipse%e5%b0%87-gradle-project-%e6%89%93%e5%8c%85%e5%81%9awar%e6%aa%94/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1002</post-id>	</item>
	</channel>
</rss>
