Skip to content

Commit

Permalink
GEODE-6557: Moving geode-web classes to geode-web
Browse files Browse the repository at this point in the history
Moving the classes in geode-core that really should be in geode-web.
This removes optional dependencies from geode-core and puts these
classes where their tests are.

As part of this change, SerializableObjectHttpMessageConverter is now
duplicated in geode-web as ServerSerializableObjectHttpMessageConverter.
This class was previously put in both the geode-web.war file and the
gfsh-dependencies by creating a separate jar with all of the geode-web
classes as part of the geode-core build.

This class is used by both gfsh and geode-web. But geode-web needs its
own copy so that the class is loaded by the geode-web war classloader in
order to ensure the class is linked with the spring-web classes coming
from the geode-web classloader.
  • Loading branch information
upthewaterspout authored Mar 27, 2019
1 parent 4848ef5 commit afb3a4f
Show file tree
Hide file tree
Showing 16 changed files with 152 additions and 136 deletions.
5 changes: 0 additions & 5 deletions geode-assembly/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -334,17 +334,13 @@ task configureGfshDepsJar(dependsOn: configurations.gfshDependencies.dependencie
inputs.files {
configureDepsJar
}
inputs.files {
project(':geode-core').webJar
}

def output = project.buildDir.toPath().resolve('reports').resolve('gfsh_deps_jar_cp.txt')
outputs.file {
output
}
doLast {
def classpath = configureDepsJar.outputs.files.singleFile.text + ' ' +
project(':geode-core').webJar.archiveName + ' ' +
configurations.gfshDependencies.collect { it.getName() }.flatten().join(' ')
output.write(classpath)
}
Expand Down Expand Up @@ -502,7 +498,6 @@ distributions {

//These tasks are included as closures (wrapped in {}) because gradle may evaluate
//this CopySpec before it evaluates the geode-core build file.
from { project(':geode-core').webJar }
from { project(':geode-core').raJar }
from { project(':geode-core').jcaJar }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,6 @@ lib/geode-protobuf-0.0.0.jar
lib/geode-protobuf-messages-0.0.0.jar
lib/geode-rebalancer-0.0.0.jar
lib/geode-wan-0.0.0.jar
lib/geode-web-0.0.0.jar
lib/gfsh-dependencies.jar
lib/grumpy-core-0.2.2.jar
lib/httpclient-4.5.6.jar
Expand Down
23 changes: 2 additions & 21 deletions geode-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ jar {
from sourceSets.main.output
from sourceSets.jca.output

exclude 'org/apache/geode/management/internal/web/**'
exclude 'org/apache/geode/internal/i18n/StringIdResourceBundle_ja.txt'
exclude 'org/apache/geode/admin/doc-files/ds4_0.dtd'

Expand All @@ -125,13 +124,6 @@ jar {

jar.dependsOn(createVersionPropertiesFile)

task webJar(type: Jar, dependsOn: classes) {
description 'Assembles the jar archive containing the gemfire management web classes.'
from sourceSets.main.output
baseName 'geode-web'
include 'org/apache/geode/management/internal/web/**'
}

task raJar(type: Jar, dependsOn: classes) {
description 'Assembles the jar archive that contains the JCA classes'
from sourceSets.jca.output
Expand Down Expand Up @@ -300,19 +292,8 @@ dependencies {
implementation('org.eclipse.jetty:jetty-server')


//Spring webmvc is used by the REST management API
compileOnly('org.springframework:spring-webmvc') {
exclude module: 'aopalliance'
exclude module: 'spring-aop'
ext.optional = true
}
//Spring webmvc is used by the REST management API
testCompile('org.springframework:spring-webmvc') {
exclude module: 'aopalliance'
exclude module: 'spring-aop'
ext.optional = true
}
//Spring core is used by the REST API, and the gfsh cli

//Spring core is used by the the gfsh cli
implementation('org.springframework:spring-core') {
ext.optional = true
}
Expand Down
2 changes: 0 additions & 2 deletions geode-pulse/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,7 @@ artifacts {
war {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
classpath configurations.runtimeClasspath
classpath project(':geode-core').webJar.archivePath
}
war.dependsOn(':geode-core:webJar')
uiTest.dependsOn war
uiTest.finalizedBy rootProject.combineReports
rootProject.combineReports.mustRunAfter uiTest
93 changes: 29 additions & 64 deletions geode-web/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,86 +21,51 @@ apply from: "${project.projectDir}/../gradle/publish.gradle"


dependencies {
compile(platform(project(':boms:geode-all-bom')))
compileOnly('javax.servlet:javax.servlet-api')
testCompile('javax.servlet:javax.servlet-api')
compileOnly(project(path: ':geode-core', configuration: 'classesOutput'))
api(platform(project(':boms:geode-all-bom')))

runtimeOnly('org.springframework:spring-aspects') {
exclude module: 'aspectjweaver'
exclude module: 'aopalliance'
exclude module: 'spring-core'
}
runtimeOnly('org.springframework:spring-oxm') {
exclude module: 'commons-logging'
exclude module: 'spring-beans'
exclude module: 'spring-core'
}
runtimeOnly('org.springframework:spring-webmvc') {
exclude module: 'aopalliance'
exclude module: 'aspectjweaver'
exclude module: 'spring-core'
}
runtimeOnly('commons-fileupload:commons-fileupload') {
exclude module: 'commons-io'
//Note - marking these deps as providedCompile means that we will exclude them and all of their
//transitive dependencies from geode-web.war. Since geode-web.war is ony run within
//a container that has geode-core on the classpath, is prevents duplicating jars. geode-core
//in particular should not be duplicated in the war.
providedCompile(project(path: ':geode-core')) {
//spring-web is excluded from the providedCompile configuration to ensure
//that it is included as part of the war. spring-web must be loaded with the war's
//classloader to interoperate correctly with it's optional dependences that are included
//in this war, in particular commons-fileupload.
exclude module: 'spring-web'
}
providedCompile(platform(project(':boms:geode-all-bom')))
providedCompile('javax.servlet:javax.servlet-api')
providedCompile('org.apache.logging.log4j:log4j-api')

testCompile(project(':geode-core'))
testCompile(project(':geode-junit')) {
exclude module: 'geode-core'
}
// have to use output since we exclude the dependent classes from jar :(
testCompile(project(path: ':geode-core', configuration: 'classesOutput'))
testCompile(project(':geode-junit')) {
exclude module: 'geode-core'
}
testCompile('org.springframework:spring-test')
testCompile('org.springframework:spring-webmvc') {
exclude module: 'aopalliance'
exclude module: 'spring-aop'
}
implementation('org.springframework:spring-webmvc')


integrationTestCompile(project(':geode-dunit'));

integrationTestRuntime(files(war.destinationDir))
integrationTestRuntime('org.springframework:spring-webmvc') {
exclude module: 'aopalliance'
exclude module: 'spring-aop'
runtimeOnly('org.springframework:spring-aspects') {
exclude module: 'aspectjweaver'
}
runtimeOnly('org.springframework:spring-oxm')
runtimeOnly('commons-fileupload:commons-fileupload')

testImplementation(project(':geode-junit'))
testImplementation('org.springframework:spring-test')

distributedTestCompile(project(':geode-common'))
distributedTestCompile(project(':geode-dunit'))
distributedTestCompile('pl.pragmatists:JUnitParams')
integrationTestImplementation(project(':geode-dunit'));

distributedTestRuntime(files(war.destinationDir))
distributedTestRuntime('org.springframework:spring-webmvc') {
exclude module: 'aopalliance'
exclude module: 'spring-aop'
}
integrationTestRuntimeOnly(files(war.destinationDir))

upgradeTestCompile(project(':geode-dunit')) {
exclude module: 'geode-core'
}
}
distributedTestImplementation(project(':geode-common'))
distributedTestImplementation(project(':geode-dunit'))
distributedTestImplementation('pl.pragmatists:JUnitParams')

distributedTestRuntimeOnly(files(war.destinationDir))

//Remove the gradle output directories from the eclipse classpath. These
//are added by the classesOutput configuration, above. Unfortunately, using
//minusConfigurations does not work here, because it removes the entire
//geode-core project
eclipse.classpath.file {
whenMerged { classpath ->
classpath.entries.removeAll { entry -> entry.path.contains('geode-core/build') }
upgradeTestImplementation(project(':geode-dunit')) {
}
}

distributedTest.dependsOn(war)
integrationTest.dependsOn(war)

war {
dependsOn ':geode-core:webJar'
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
classpath configurations.runtimeClasspath
classpath project(':geode-core').webJar.archivePath
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* 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 org.apache.geode.management.internal.web.http.converter;

import java.io.IOException;
import java.io.Serializable;

import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.StreamUtils;

import org.apache.geode.internal.util.IOUtils;

/**
* The ServerSerializableObjectHttpMessageConverter class is a Spring HttpMessageConverter for
* converting
* bytes streams to/from Serializable Objects.
*
* This class is the same as {@link ServerSerializableObjectHttpMessageConverter}. However, to
* avoid classloader issues due to the fact that geode-web.war needs to use this converter
* as well as geode-core (because the converter is used by gfsh), this class is duplicated in
* geode-web. This ensures that the version used by the war will implement
* {@link HttpMessageConverter}
* from the geode-web war's classloader rather than geode-core's classloader and interoperate
* with other classes loaded in the geode-web war's classloader.
* <p/>
*
* @see Serializable
* @see HttpInputMessage
* @see HttpMessage
* @see HttpOutputMessage
* @see MediaType
* @see AbstractHttpMessageConverter
* @since GemFire 8.0
*/
@SuppressWarnings("unused")
public class ServerSerializableObjectHttpMessageConverter
extends AbstractHttpMessageConverter<Serializable> {

public ServerSerializableObjectHttpMessageConverter() {
super(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL);
}

@Override
protected boolean supports(final Class<?> type) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("%1$s.supports(%2$s)", getClass().getName(), type.getName()),
new Throwable());
}

return (type != null && Serializable.class.isAssignableFrom(type));
}

@Override
protected Serializable readInternal(final Class<? extends Serializable> type,
final HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
try {
ClassLoader classLoader = type.getClassLoader();
return type.cast(IOUtils.deserializeObject(IOUtils.toByteArray(inputMessage.getBody()),
classLoader != null ? classLoader : getClass().getClassLoader()));
} catch (ClassNotFoundException e) {
throw new HttpMessageNotReadableException(
String.format("Unable to convert the HTTP message body into an Object of type (%1$s)",
type.getName()),
e);
}
}

protected void setContentLength(final HttpMessage message, final byte[] messageBody) {
message.getHeaders().setContentLength(messageBody.length);
}

@Override
protected void writeInternal(final Serializable serializableObject,
final HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
final byte[] messageBody = IOUtils.serializeObject(serializableObject);
setContentLength(outputMessage, messageBody);
StreamUtils.copy(messageBody, outputMessage.getBody());
}

}
2 changes: 1 addition & 1 deletion geode-web/src/main/webapp/WEB-INF/geode-mgmt-servlet.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ limitations under the License.
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>
<bean class="org.apache.geode.management.internal.web.http.converter.SerializableObjectHttpMessageConverter"/>
<bean class="org.apache.geode.management.internal.web.http.converter.ServerSerializableObjectHttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>

Expand Down
Loading

0 comments on commit afb3a4f

Please sign in to comment.