openwhisk-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pde...@apache.org
Subject [openwhisk-devtools] branch master updated: Fix gradle build for Java runtime (#285)
Date Thu, 29 Aug 2019 17:47:11 GMT
This is an automated email from the ASF dual-hosted git repository.

pdesai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openwhisk-devtools.git


The following commit(s) were added to refs/heads/master by this push:
     new 0e0141d  Fix gradle build for Java runtime (#285)
0e0141d is described below

commit 0e0141d503a9a23b717fe7fc88c79e30895d99b7
Author: Matt Rutkowski <mrutkows@us.ibm.com>
AuthorDate: Thu Aug 29 12:47:07 2019 -0500

    Fix gradle build for Java runtime (#285)
    
    * Fix gradle build for Java runtime
    
    * Fix gradle build for Java runtime
---
 .../java8/proxy/profiles/base/profile.properties}  |  28 +-
 .../proxy/profiles/spring/profile.properties}      |  21 +-
 knative-build/runtimes/java/gradlew                |  18 +-
 knative-build/runtimes/java/gradlew.bat            |  84 -----
 knative-build/runtimes/java/settings.gradle        |   2 +-
 .../java/tests/src/test/resources/application.conf |  22 --
 .../JavaActionContainerTests.scala                 | 417 ---------------------
 7 files changed, 20 insertions(+), 572 deletions(-)

diff --git a/knative-build/runtimes/java/tests/build.gradle b/knative-build/runtimes/java/core/java8/proxy/profiles/base/profile.properties
similarity index 51%
rename from knative-build/runtimes/java/tests/build.gradle
rename to knative-build/runtimes/java/core/java8/proxy/profiles/base/profile.properties
index 1ae5a4b..b7a7e77 100644
--- a/knative-build/runtimes/java/tests/build.gradle
+++ b/knative-build/runtimes/java/core/java8/proxy/profiles/base/profile.properties
@@ -15,30 +15,4 @@
  * limitations under the License.
  */
 
-apply plugin: 'scala'
-apply plugin: 'eclipse'
-compileTestScala.options.encoding = 'UTF-8'
-
-repositories {
-    mavenCentral()
-    mavenLocal()
-}
-
-tasks.withType(Test) {
-    testLogging {
-        events "passed", "skipped", "failed"
-        showStandardStreams = true
-        exceptionFormat = 'full'
-    }
-    outputs.upToDateWhen { false } // force tests to run every time
-}
-
-dependencies {
-    compile "org.scala-lang:scala-library:${gradle.scala.version}"
-    compile "org.apache.openwhisk:openwhisk-tests:${gradle.openwhisk.version}:tests"
-    compile "org.apache.openwhisk:openwhisk-tests:${gradle.openwhisk.version}:test-sources"
-}
-
-tasks.withType(ScalaCompile) {
-    scalaCompileOptions.additionalParameters = gradle.scala.compileFlags
-}
+compile.gson=com.google.code.gson:gson:2.6.2
diff --git a/knative-build/runtimes/java/settings.gradle b/knative-build/runtimes/java/core/java8/proxy/profiles/spring/profile.properties
similarity index 65%
copy from knative-build/runtimes/java/settings.gradle
copy to knative-build/runtimes/java/core/java8/proxy/profiles/spring/profile.properties
index 464ae37..b7a7e77 100644
--- a/knative-build/runtimes/java/settings.gradle
+++ b/knative-build/runtimes/java/core/java8/proxy/profiles/spring/profile.properties
@@ -15,23 +15,4 @@
  * limitations under the License.
  */
 
-include 'tests'
-
-include 'core:java8'
-include 'core:java8:proxy'
-
-rootProject.name = 'runtime-java'
-
-gradle.ext.openwhisk = [
-        version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
-    version: '2.12.7',
-    compileFlags: ['-feature', '-unchecked', '-deprecation', '-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
-    version: '1.5.0',
-    config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+compile.gson=com.google.code.gson:gson:2.6.2
diff --git a/knative-build/runtimes/java/gradlew b/knative-build/runtimes/java/gradlew
index cccdd3d..d4ee78f 100755
--- a/knative-build/runtimes/java/gradlew
+++ b/knative-build/runtimes/java/gradlew
@@ -1,5 +1,21 @@
 #!/usr/bin/env sh
 
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
 ##############################################################################
 ##
 ##  Gradle start up script for UN*X
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
 APP_BASE_NAME=`basename "$0"`
 
 # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options
to this script.
-DEFAULT_JVM_OPTS=""
+DEFAULT_JVM_OPTS='-Dfile.encoding=UTF-8'
 
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD="maximum"
diff --git a/knative-build/runtimes/java/gradlew.bat b/knative-build/runtimes/java/gradlew.bat
deleted file mode 100644
index e95643d..0000000
--- a/knative-build/runtimes/java/gradlew.bat
+++ /dev/null
@@ -1,84 +0,0 @@
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem  Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM
options to this script.
-set DEFAULT_JVM_OPTS=
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto init
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%"
-classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/knative-build/runtimes/java/settings.gradle b/knative-build/runtimes/java/settings.gradle
index 464ae37..3f317f7 100644
--- a/knative-build/runtimes/java/settings.gradle
+++ b/knative-build/runtimes/java/settings.gradle
@@ -18,7 +18,7 @@
 include 'tests'
 
 include 'core:java8'
-include 'core:java8:proxy'
+//include 'core:java8:proxy'
 
 rootProject.name = 'runtime-java'
 
diff --git a/knative-build/runtimes/java/tests/src/test/resources/application.conf b/knative-build/runtimes/java/tests/src/test/resources/application.conf
deleted file mode 100644
index c448e38..0000000
--- a/knative-build/runtimes/java/tests/src/test/resources/application.conf
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-whisk.spi {
-  SimpleSpi = whisk.spi.SimpleSpiImpl
-  MissingSpi = whisk.spi.MissingImpl
-  MissingModule = missing.module
-}
diff --git a/knative-build/runtimes/java/tests/src/test/scala/actionContainers/JavaActionContainerTests.scala
b/knative-build/runtimes/java/tests/src/test/scala/actionContainers/JavaActionContainerTests.scala
deleted file mode 100644
index a990f33..0000000
--- a/knative-build/runtimes/java/tests/src/test/scala/actionContainers/JavaActionContainerTests.scala
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package actionContainers
-
-import org.junit.runner.RunWith
-import org.scalatest.junit.JUnitRunner
-import common.WskActorSystem
-import spray.json.DefaultJsonProtocol._
-import spray.json._
-import actionContainers.ResourceHelpers.JarBuilder
-import actionContainers.ActionContainer.withContainer
-
-@RunWith(classOf[JUnitRunner])
-class JavaActionContainerTests extends BasicActionRunnerTests with WskActorSystem {
-
-  // Helpers specific to java actions
-  override def withActionContainer(env: Map[String, String] = Map.empty)(
-    code: ActionContainer => Unit): (String, String) = withContainer("java8action", env)(code)
-
-  behavior of "Java action"
-
-  override val testNoSourceOrExec = {
-    TestConfig("")
-  }
-
-  override val testNotReturningJson = {
-    // skip this test since and add own below (see Nuller)
-    TestConfig("", skipTest = true)
-  }
-
-  override val testEnv = {
-    TestConfig(
-      JarBuilder.mkBase64Jar(
-        Seq("example", "HelloWhisk.java") ->
-          """
-          | package example;
-          |
-          | import com.google.gson.JsonObject;
-          |
-          | public class HelloWhisk {
-          |     public static JsonObject main(JsonObject args) {
-          |         JsonObject response = new JsonObject();
-          |         response.addProperty("api_host", System.getenv("__OW_API_HOST"));
-          |         response.addProperty("api_key", System.getenv("__OW_API_KEY"));
-          |         response.addProperty("namespace", System.getenv("__OW_NAMESPACE"));
-          |         response.addProperty("action_name", System.getenv("__OW_ACTION_NAME"));
-          |         response.addProperty("activation_id", System.getenv("__OW_ACTIVATION_ID"));
-          |         response.addProperty("deadline", System.getenv("__OW_DEADLINE"));
-          |         return response;
-          |     }
-          | }
-        """.stripMargin.trim),
-      main = "example.HelloWhisk")
-  }
-
-  override val testEcho = {
-    TestConfig(
-      JarBuilder.mkBase64Jar(
-        Seq("example", "HelloWhisk.java") ->
-          """
-          | package example;
-          |
-          | import com.google.gson.JsonObject;
-          |
-          | public class HelloWhisk {
-          |     public static JsonObject main(JsonObject args) {
-          |         System.out.println("hello stdout");
-          |         System.err.println("hello stderr");
-          |         return args;
-          |     }
-          | }
-        """.stripMargin.trim),
-      "example.HelloWhisk")
-  }
-
-  override val testUnicode = {
-    TestConfig(
-      JarBuilder.mkBase64Jar(
-        Seq("example", "HelloWhisk.java") ->
-          """
-          | package example;
-          |
-          | import com.google.gson.JsonObject;
-          |
-          | public class HelloWhisk {
-          |     public static JsonObject main(JsonObject args) {
-          |         String delimiter = args.getAsJsonPrimitive("delimiter").getAsString();
-          |         JsonObject response = new JsonObject();
-          |          String str = delimiter + " ☃ " + delimiter;
-          |          System.out.println(str);
-          |          response.addProperty("winter", str);
-          |          return response;
-          |     }
-          | }
-        """.stripMargin),
-      "example.HelloWhisk")
-  }
-
-  def echo(main: String = "main") = {
-    JarBuilder.mkBase64Jar(
-      Seq("example", "HelloWhisk.java") ->
-        s"""
-        | package example;
-        |
-        | import com.google.gson.JsonObject;
-        |
-        | public class HelloWhisk {
-        |     public static JsonObject $main(JsonObject args) {
-        |         return args;
-        |     }
-        | }
-      """.stripMargin.trim)
-  }
-
-  override val testInitCannotBeCalledMoreThanOnce = {
-    TestConfig(echo(), "example.HelloWhisk")
-  }
-
-  override val testEntryPointOtherThanMain = {
-    TestConfig(echo("naim"), "example.HelloWhisk#naim")
-  }
-
-  override val testLargeInput = {
-    TestConfig(echo(), "example.HelloWhisk")
-  }
-
-  Seq("", "x", "!", "#", "#main", "#bogus").foreach { m =>
-    it should s"report an error if explicit 'main' is not found ($m)" in {
-      val (out, err) = withActionContainer() { c =>
-        val (initCode, out) = c.init(initPayload(echo("hello"), s"example.HelloWhisk$m"))
-        initCode shouldBe 502
-
-        out shouldBe {
-          val error = m match {
-            case c if c == "x" || c == "!" => s"java.lang.ClassNotFoundException: example.HelloWhisk$c"
-            case "#bogus"                  => "java.lang.NoSuchMethodException: example.HelloWhisk.bogus(com.google.gson.JsonObject)"
-            case _                         => "java.lang.NoSuchMethodException: example.HelloWhisk.main(com.google.gson.JsonObject)"
-          }
-          Some(JsObject("error" -> s"An error has occurred (see logs for details): $error".toJson))
-        }
-      }
-
-      checkStreams(out, err, {
-        case (o, e) =>
-          o shouldBe empty
-          e should not be empty
-      })
-    }
-  }
-
-  it should "fail to initialize with bad code" in {
-    val (out, err) = withActionContainer() { c =>
-      // This is valid zip file containing a single file, but not a valid
-      // jar file.
-      val brokenJar = ("UEsDBAoAAAAAAPxYbkhT4iFbCgAAAAoAAAANABwAbm90YWNsYXNzZmlsZVV" +
-        "UCQADzNPmVszT5lZ1eAsAAQT1AQAABAAAAABzYXVjaXNzb24KUEsBAh4DCg" +
-        "AAAAAA/FhuSFPiIVsKAAAACgAAAA0AGAAAAAAAAQAAAKSBAAAAAG5vdGFjb" +
-        "GFzc2ZpbGVVVAUAA8zT5lZ1eAsAAQT1AQAABAAAAABQSwUGAAAAAAEAAQBT" +
-        "AAAAUQAAAAAA")
-
-      val (initCode, _) = c.init(initPayload(brokenJar, "example.Broken"))
-      initCode should not be (200)
-    }
-
-    // Somewhere, the logs should contain an exception.
-    checkStreams(out, err, {
-      case (o, e) =>
-        (o + e).toLowerCase should include("exception")
-    })
-  }
-
-  it should "return some error on action error" in {
-    val (out, err) = withActionContainer() { c =>
-      val jar = JarBuilder.mkBase64Jar(
-        Seq("example", "HelloWhisk.java") ->
-          """
-            | package example;
-            |
-            | import com.google.gson.JsonObject;
-            |
-            | public class HelloWhisk {
-            |     public static JsonObject main(JsonObject args) throws Exception {
-            |         throw new Exception("noooooooo");
-            |     }
-            | }
-          """.stripMargin.trim)
-
-      val (initCode, _) = c.init(initPayload(jar, "example.HelloWhisk"))
-      initCode should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject.empty))
-      runCode should not be (200)
-
-      runRes shouldBe defined
-      runRes.get.fields.get("error") shouldBe defined
-    }
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        (o + e).toLowerCase should include("exception")
-    })
-  }
-
-  it should "support application errors" in {
-    val (out, err) = withActionContainer() { c =>
-      val jar = JarBuilder.mkBase64Jar(
-        Seq("example", "Error.java") ->
-          """
-            | package example;
-            |
-            | import com.google.gson.JsonObject;
-            |
-            | public class Error {
-            |     public static JsonObject main(JsonObject args) throws Exception {
-            |         JsonObject error = new JsonObject();
-            |         error.addProperty("error", "This action is unhappy.");
-            |         return error;
-            |     }
-            | }
-          """.stripMargin.trim)
-
-      val (initCode, _) = c.init(initPayload(jar, "example.Error"))
-      initCode should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject.empty))
-      runCode should be(200) // action writer returning an error is OK
-
-      runRes shouldBe defined
-      runRes.get.fields.get("error") shouldBe defined
-    }
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        o shouldBe empty
-        e shouldBe empty
-    })
-  }
-
-  it should "support main in default package" in {
-    val (out, err) = withActionContainer() { c =>
-      val jar = JarBuilder.mkBase64Jar(
-        Seq("", "HelloWhisk.java") ->
-          """
-            | import com.google.gson.JsonObject;
-            |
-            | public class HelloWhisk {
-            |     public static JsonObject main(JsonObject args) throws Exception {
-            |         return args;
-            |     }
-            | }
-          """.stripMargin.trim)
-
-      val (initCode, _) = c.init(initPayload(jar, "HelloWhisk"))
-      initCode should be(200)
-
-      val args = JsObject("a" -> "A".toJson)
-      val (runCode, runRes) = c.run(runPayload(args))
-      runCode should be(200)
-      runRes shouldBe Some(args)
-    }
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        o shouldBe empty
-        e shouldBe empty
-    })
-  }
-
-  it should "survive System.exit" in {
-    val (out, err) = withActionContainer() { c =>
-      val jar = JarBuilder.mkBase64Jar(
-        Seq("example", "Quitter.java") ->
-          """
-            | package example;
-            |
-            | import com.google.gson.*;
-            |
-            | public class Quitter {
-            |     public static JsonObject main(JsonObject main) {
-            |         System.exit(1);
-            |         return new JsonObject();
-            |     }
-            | }
-          """.stripMargin.trim)
-
-      val (initCode, _) = c.init(initPayload(jar, "example.Quitter"))
-      initCode should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject.empty))
-      runCode should not be (200)
-
-      runRes shouldBe defined
-      runRes.get.fields.get("error") shouldBe defined
-    }
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        (o + e).toLowerCase should include("system.exit")
-    })
-  }
-
-  it should "enforce that the user returns an object" in {
-    val (out, err) = withActionContainer() { c =>
-      val jar = JarBuilder.mkBase64Jar(
-        Seq("example", "Nuller.java") ->
-          """
-            | package example;
-            |
-            | import com.google.gson.*;
-            |
-            | public class Nuller {
-            |     public static JsonObject main(JsonObject args) {
-            |         return null;
-            |     }
-            | }
-          """.stripMargin.trim)
-
-      val (initCode, _) = c.init(initPayload(jar, "example.Nuller"))
-      initCode should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject.empty))
-      runCode should not be (200)
-
-      runRes shouldBe defined
-      runRes.get.fields.get("error") shouldBe defined
-    }
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        (o + e).toLowerCase should include("the action returned null")
-    })
-  }
-
-  val dynamicLoadingJar = JarBuilder.mkBase64Jar(
-    Seq(
-      Seq("example", "EntryPoint.java") ->
-        """
-          | package example;
-          |
-          | import com.google.gson.*;
-          | import java.lang.reflect.*;
-          |
-          | public class EntryPoint {
-          |     private final static String CLASS_NAME = "example.DynamicClass";
-          |     public static JsonObject main(JsonObject args) throws Exception {
-          |         String cl = args.getAsJsonPrimitive("classLoader").getAsString();
-          |
-          |         Class d = null;
-          |         if("local".equals(cl)) {
-          |             d = Class.forName(CLASS_NAME);
-          |         } else if("thread".equals(cl)) {
-          |             d = Thread.currentThread().getContextClassLoader().loadClass(CLASS_NAME);
-          |         }
-          |
-          |         Object o = d.newInstance();
-          |         Method m = o.getClass().getMethod("getMessage");
-          |         String msg = (String)m.invoke(o);
-          |
-          |         JsonObject response = new JsonObject();
-          |         response.addProperty("message", msg);
-          |         return response;
-          |     }
-          | }
-        """.stripMargin.trim,
-      Seq("example", "DynamicClass.java") ->
-        """
-          | package example;
-          |
-          | public class DynamicClass {
-          |     public String getMessage() {
-          |         return "dynamic!";
-          |     }
-          | }
-        """.stripMargin.trim))
-
-  def classLoaderTest(param: String) = {
-    val (out, err) = withActionContainer() { c =>
-      val (initCode, _) = c.init(initPayload(dynamicLoadingJar, "example.EntryPoint"))
-      initCode should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject("classLoader" -> JsString(param))))
-      runCode should be(200)
-
-      runRes shouldBe defined
-      runRes.get.fields.get("message") shouldBe Some(JsString("dynamic!"))
-    }
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        o shouldBe empty
-        e shouldBe empty
-    })
-  }
-
-  it should "support loading classes from the current classloader" in {
-    classLoaderTest("local")
-  }
-
-  it should "support loading classes from the Thread classloader" in {
-    classLoaderTest("thread")
-  }
-}


Mime
View raw message