Gatling Proxy configuration fails - scala

When doing this
val HTTP_PROTOCOL = http
.proxy(Proxy("proxy", 8080))
I have this when launching my tests
too many arguments (2) for method apply:(v1:io.gatling.core.session.Session)io.gatling.commons.validation.Validation[Proxy.type] in trait Function1
.proxy(Proxy("proxy", 8080))
The doc doesn't mention anything about anything else
https://gatling.io/docs/current/http/http_protocol#response-handling-parameters
I'm using the latest versions available
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<encoding>UTF-8</encoding>
<gatling.version>3.3.1</gatling.version>
<gatling-maven-plugin.version>3.0.5</gatling-maven-plugin.version>
</properties>
Any idea as it may be some Scala issue ?

proxy can be invoked:
either on an HttpProtocol like in here
or on an HttpRequestBuilder like in here
So either you're not calling it at the right place, or you've messed up with the Gatling imports, which should strictly be like in here.
The doc doesn't mention anything about anything else
The correct links to the doc about proxy are:
https://gatling.io/docs/current/http/http_protocol#proxy-parameters
https://gatling.io/docs/current/http/http_request#outgoing-proxy

Related

Quarkus native build Random/SplittableRandom exception with Vert.x Redis Client

I am doing a native build of my Quarkus app and am hitting the UnsupportedFeatureException: Detected an instance of Random/SplittableRandom on a few Vertx Redis Client classes.
I am building using the docker container method:
./mvnw package -Dnative -Dquarkus.native.container-build=true
I have fixed some of the exceptions by including in the pom.xml:
<quarkus.native.additional-build-args>
--initialize-at-run-time=io.vertx.redis.client.impl.RedisSentinelClient
</quarkus.native.additional-build-args>
but am stuck on this one:
Fatal error: com.oracle.graal.pointsto.util.AnalysisError$ParsingError: Error encountered while parsing
io.vertx.redis.client.impl.RedisClusterConnection.send(io.vertx.redis.client.Request)
Parsing context:
at io.vertx.redis.client.impl.RedisClusterConnection.send(RedisClusterConnection.java:117)
at io.vertx.redis.client.impl.BaseRedisClient.lambda$send$1(BaseRedisClient.java:45)
at io.vertx.redis.client.impl.BaseRedisClient$$Lambda$1711/0x00000007c1ea57e8.apply(Unknown Source)
I have tried adding
--initialize-at-run-time=io.vertx.redis.client.impl.RedisSentinelClient\,io.vertx.redis.client.impl.RedisClusterConnection
--initialize-at-run-time=io.vertx.redis.client.impl.RedisSentinelClient\,io.vertx.redis.client.impl.BaseRedisClient
and even
--initialize-at-run-time=io.vertx.redis.client.impl.RedisSentinelClient\,io.vertx.redis.client.impl.RedisReplicationConnection.send(io.vertx.redis.client.Request)
but the error persists.
I am fairly new to Java and very new to native building / GraalVM etc
Can anyone shed any light on what class I should add, please?
Thanks,
Murray
I believe we can propose a change to vert.x redis client to avoid the split random use. The randomness is there mostly to share the load across nodes. It is not used for any security related features. For this reason, a proposal to either round-robin would probably make more sense as a solution to this issue.
Ok, this seems to fix it:
EDIT: No it doesn't. See below.
<quarkus.native.additional-build-args>
--initialize-at-run-time=io.vertx.redis.client.impl.RedisSentinelClient\,io.vertx.redis.client.impl.RedisReplicationConnection
</quarkus.native.additional-build-args>
The full profiles section in the pom.xml looks like this, for anyone else new to all this.
<profiles>
<profile>
<id>native</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<properties>
<skipITs>false</skipITs>
<quarkus.package.type>native</quarkus.package.type>
<quarkus.native.additional-build-args>
--initialize-at-run-time=io.vertx.redis.client.impl.RedisSentinelClient\,io.vertx.redis.client.impl.RedisReplicationConnection
</quarkus.native.additional-build-args>
</properties>
</profile>
</profiles>
I have different errors now, so still not building, but at least this seems to fix that specific issue.
EDIT: The problem persists...
If I build with the pom as described above, ie:
<quarkus.native.additional-build-args>
--initialize-at-run-time=io.vertx.redis.client.impl.RedisSentinelClient\,io.vertx.redis.client.impl.RedisReplicationConnection
</quarkus.native.additional-build-args>
I now get:
Error: Classes that should be initialized at run time got initialized during image building:
io.vertx.redis.client.impl.RedisReplicationConnection
the class was requested to be initialized at run time
(from command line with 'io.vertx.redis.client.impl.RedisReplicationConnection').
So, I guess that is not the right class afterall.
If I remove that class from the list I revert to the Random exception.
(Showing more detail)
[1/7] Initializing... (3.7s # 0.10GB)
Version info: 'GraalVM 22.3.1.0-Final Java 17 Mandrel Distribution'
Java version info: '17.0.6+10'
C compiler: gcc (linux, x86_64, 11.3.0)
Garbage collector: Serial GC
4 user-specific feature(s)
- io.quarkus.runner.Feature: Auto-generated class by Quarkus from the existing extensions
- io.quarkus.runtime.graal.DisableLoggingFeature: Disables INFO logging during the analysis phase for the [org.jboss.threads] categories
- io.quarkus.runtime.graal.ResourcesFeature: Register each line in META-INF/quarkus-native-resources.txt as a resource on Substrate VM
- io.quarkus.websockets.client.runtime.DisableLoggingFeature: Disables INFO logging during the analysis phase for the [io.undertow.websockets] categories
[2/7] Performing analysis... [*] (14.1s # 3.37GB)
12,032 (89.58%) of 13,432 classes reachable
17,778 (59.65%) of 29,803 fields reachable
61,621 (57.16%) of 107,809 methods reachable
541 classes, 150 fields, and 2,655 methods registered for reflection
Fatal error: com.oracle.graal.pointsto.util.AnalysisError$ParsingError: Error encountered while parsing io.vertx.redis.client.impl.RedisReplicationConnection.send(io.vertx.redis.client.Request)
Parsing context:
at io.vertx.redis.client.impl.RedisReplicationConnection.send(RedisReplicationConnection.java:111)
at io.vertx.redis.client.RedisConnection.send(RedisConnection.java:83)
at io.vertx.redis.client.impl.RedisReplicationClient.getNodes(RedisReplicationClient.java:183)
at io.vertx.redis.client.impl.RedisReplicationClient.lambda$connect$4(RedisReplicationClient.java:126)
at io.vertx.redis.client.impl.RedisReplicationClient$$Lambda$2203/0x00000007c1630f60.handle(Unknown Source)
at io.vertx.core.impl.future.FutureImpl$1.onSuccess(FutureImpl.java:91)
{etc}
I am beginning to think I have an error / issue in my code where I am using the Vert.x Redis Client. I am trying to narrow it down by trial and error.
Any other suggestions are most welcome.

List container metadata from non-Keystone Swift

This code makes GET request to RadosGW (I don't use Keystone)
String srcEndpoint = "http://myhost/auth/v1.0";
SwiftApi api = ContextBuilder.newBuilder(PROVIDER).endpoint(srcEndpoint)
.credentials(srcIdentity, srcCredential).buildApi(SwiftApi.class);
If PROVIDER is openstack-swift my code throws
org.jclouds.http.HttpResponseException: command: POST http://myhost/auth/v1.0/tokens HTTP/1.1 failed with response: HTTP/1.1 405 Method Not Allowed; content: [{"Code":"MethodNotAllowed"}]
If PROVIDER is swift my code throws
Exception in thread "main" com.google.inject.ConfigurationException: Guice configuration errors:
1) No implementation for org.jclouds.openstack.swift.v1.SwiftApi was bound.
while locating org.jclouds.openstack.swift.v1.SwiftApi
My dependencies are
<dependency>
<groupId>org.apache.jclouds.api</groupId>
<artifactId>swift</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.apache.jclouds.api</groupId>
<artifactId>openstack-swift</artifactId>
<version>1.9.2</version>
</dependency>
How can I list all containers with all their metadata, without downloading the list of blobs it contains?
What's the difference between swift and openstack-swift?
The primary difference is that swift supports v1 auth and openstack-swift supports v2 auth. Unfortunately, swift is also deprecated and no longer maintained.
The reason you are getting that error is because SwiftApi is specific to the openstack-swift API implementation. Despite the heroic efforts that jclouds makes to abstract away all the implementation details, it's not perfect. The swift API implementation returns SwiftClient, which extends CommonSwiftClient (where all the interesting methods are defined).
Also, as you may have guessed, SwiftClient is in a different package. So be sure to include package org.jclouds.openstack.swift; (no ".v1")
You can list all containers with their metadata by calling listContainers(ListContainerOptions... options) on your SwiftClient instance. This will return Set<ContainerMetadata>.

How to suppress Spark logging in unit tests?

So thanks to easily googleable blogs I tried:
import org.specs2.mutable.Specification
class SparkEngineSpecs extends Specification {
sequential
def setLogLevels(level: Level, loggers: Seq[String]): Map[String, Level] = loggers.map(loggerName => {
val logger = Logger.getLogger(loggerName)
val prevLevel = logger.getLevel
logger.setLevel(level)
loggerName -> prevLevel
}).toMap
setLogLevels(Level.WARN, Seq("spark", "org.eclipse.jetty", "akka"))
val sc = new SparkContext(new SparkConf().setMaster("local").setAppName("Test Spark Engine"))
// ... my unit tests
But unfortunately it doesn't work, I still get a lot of spark output, e.g.:
14/12/02 12:01:56 INFO MemoryStore: Block broadcast_4 of size 4184 dropped from memory (free 583461216)
14/12/02 12:01:56 INFO ContextCleaner: Cleaned broadcast 4
14/12/02 12:01:56 INFO ContextCleaner: Cleaned shuffle 4
14/12/02 12:01:56 INFO ShuffleBlockManager: Deleted all files for shuffle 4
Add the following code into the log4j.properties file inside the src/test/resources dir, create the file/dir if not exist
# Change this to set Spark log level
log4j.logger.org.apache.spark=WARN
# Silence akka remoting
log4j.logger.Remoting=WARN
# Ignore messages below warning level from Jetty, because it's a bit verbose
log4j.logger.org.eclipse.jetty=WARN
When I run my unit tests (I'm using JUnit and Maven), I only receive WARN level logs, in other words no more cluttering with INFO level logs (though they can be useful at times for debugging).
I hope this helps.
In my case one of my own libraries brought logback-classic into the mix. This materialized in a warning at the start:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/alex/.ivy2/cache/ch.qos.logback/logback-classic/jars/logback-classic-1.1.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/alex/.ivy2/cache/org.slf4j/slf4j-log4j12/jars/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
I solved this by excluding it from the dependency:
"com.mystuff" % "mylib" % "1.0.0" exclude("ch.qos.logback", "logback-classic")
Now I could add a log4j.properties file in test/resources which now gets used by Spark.
After some time of struggling with Spark log output as well, I found a blog post with a solution I particularly liked.
If you use slf4j, one can simply exchange the underlying log implementation. A good canidate for the test scope is slf4j-nop, which carfully takes the log output and puts it where the sun never shines.
When using Maven you can add the following to the top of your dependencies list:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.12</version>
<scope>test</scope>
</dependency>
Note that it might be important to have it at the beginning of the dependencies list to make sure that the given implementations are used instead of those that might come with other packages (and which you can consider to exclude in order to keep your class path tidy and avoid unexpected conflicts).
You can use a separate Logback config for tests. Depending on your environment it's possible that you just need to create conf/logback-test.xml with something that hides the logs. I think this should do that:
<configuration>
<root level="debug">
</root>
</configuration>
As I understand it, this captures all logs (level debug and higher) and assigns no logger to them, so they get discarded. A better option is to configure a file logger for them, so you can still access the logs if you want to.
See http://logback.qos.ch/manual/configuration.html for the detailed documentation.
A little late to the party but I found this in the spark example code :
def setStreamingLogLevels() {
val log4jInitialized = Logger.getRootLogger.getAllAppenders.hasMoreElements
if (!log4jInitialized) {
// We first log something to initialize Spark's default logging, then we override the
// logging level.
logInfo("Setting log level to [WARN] for streaming example." +
" To override add a custom log4j.properties to the classpath.")
Logger.getRootLogger.setLevel(Level.WARN)
}
}
I also found that with your code if you call setLogLevels like below it cut out alot of out put for me.
setLogLevels(Level.WARN, Seq("spark", "org", "akka"))
The easiest solution working for me is:
cp $SPARK_HOME/conf/log4j.properties.template $YOUR_PROJECT/src/test/resources/log4j.properties
sed -i -e 's/log4j.rootCategory=INFO/log4j.rootCategory=WARN/g' $YOUR_PROJECT/src/test/resources/log4j.properties

OpenEJB cannot use javax.persistence.jtaDataSource

The following configuration is ok for WebLogic, but in OpenEJB it raises a error "javax.naming.NameNotFoundException: Name "AppDB" not found."
And if I removed the property javax.persistence.jtaDataSource, it works. And why set 2 duplicated datasource? Because it's a bug of Eclipselinks (see http://bugs.eclipse.org/246126)
<persistence-unit name="app1" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>AppDB</jta-data-source>
<properties>
<property name="javax.persistence.jtaDataSource" value="AppDB" />
</properties>
</persistence-unit>
The following is jndi.properties
java.naming.factory.initial=org.apache.openejb.client.LocalInitialContextFactory
openejb.validation.output.level=VERBOSE
openejb.nobanner=false
jdbc/AppDB = new://Resource?type=DataSource
jdbc/AppDB.provider = org.eclipse.persistence.jpa.PersistenceProvider
jdbc/AppDB.JdbcDriver = oracle.jdbc.OracleDriver
jdbc/AppDB.JdbcUrl = jdbc:oracle:thin:#xx.xx.xx.xx:xxxx:xxxx
jdbc/AppDB.JtaManaged = false
jdbc/AppDB.UserName = xxxx
jdbc/AppDB.Password = xxxx
Because this is a jar packaged by other team, I cannot change the content but I still want to use it in my OpenEJB, any suggestion? thanks.
Not at all sure how EclipseLink processes the javax.persistence.jtaDataSource property. I have to assume it's a JNDI lookup of some kind, but there's incredible significance in how they might do that. If they prepend java:comp/env/ for example, that significantly changes the semantics.
Maybe try overriding javax.persistence.jtaDataSource to use the OpenEJB global JNDI name for your datasource. So in your jndi.properties file, add
app1.javax.persistence.jtaDataSource = openejb:Resource/jdbc/AppDB
Definitely let me know if that works. Seems that might a good feature to add to OpenEJB even though the property is actually used by the JPA provider. Fixing invalid JNDI names could be more than convenient.
On a side note, there should be a logging statement saying 'jdbc/AppDB.provider' is not a property supported by the datasource. Probably best to delete that property.

GWT: Servlet URL mapping gives a 404 error

I have read the other GWT Servlet questions, but I'm having trouble solving my problem still. My package is called Maps, and it has a service named MyService (which was set up according to a GWT Tutorial). The web.xml file includes the following:
<servlet>
<servlet-name>MyServiceImpl</servlet-name>
<servlet-class>com.xerox.maps.maps.server.MyServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServiceImpl</servlet-name>
<url-pattern>/Maps/service</url-pattern>
</servlet-mapping>
In MyService, I have the line:
#RemoteServiceRelativePath("service")
public interface MyService extends RemoteService { ...
However, when I try to make an RPC call, there is an error thrown. The details of the error say that it is a 404 HTTP error. How can I fix this, to make sure that the mapping is correct?
Edit 7.27
MyService.java contains the annotation:
#RemoteServiceRelativePath("service")
And web.xml contains:
<servlet-name>MyServiceImpl</servlet-name>
<url-pattern>/com.x.maps.Maps/service</url-pattern>
If I follow the XHR with FireBug, it shows me that there is a call to com.x.maps.Maps
404 Not found is thrown usually when service endpoint path is inferred wrongly by GWT. Try removing #RemoteServiceRelativePath("service") and recompile and check, If that does not work find out the URL endpoint of the service manually (by hitting likely paths from a browser till the error changes to 500 internal error) and then give the correct path as argument to #RemoteServiceRelativePath("correct/path"). Few trials I would try right away is #RemoteServiceRelativePath("/Maps/service") and #RemoteServiceRelativePath("Maps/service") without the slash
According to this tutorial:
https://developers.google.com/web-toolkit/doc/latest/tutorial/RPC
The servlet-mapping should be composed of the module "rename-to" and the service "RemoteServiceRelativePath". So, if you have, in your *.gwt.xml file, the following line:
<module rename-to='XXX'>
And in your *Service.java file you have the following line:
#RemoteServiceRelativePath("YYY")
Then, in your "web.xml" file, you should have the following lines:
<servlet-mapping>
<servlet-name>...servlet-name>
<url-pattern>/XXX/YYY</url-pattern>
</servlet-mapping>
New answer after all the comments :
Cool, you have made progress!
You are hitting this URL -
http://127.0.0.1:8888/com.x.maps.maps.Maps
With this POST data I assume - /%7C98544A4AED8C7D42E80C55859E9CEC4C%7Ccom.x.maps.maps.client.MyService%7CreadFile%7Cjava.lang.String/2004016611%7CPrinterList.xls%7C1%7C2%7C3%7C4%7C1%7C5%7C6%7C
This is where the problem is, your servlet is mapped to respond to XHR requests coming to <url-pattern>/Maps/service</url-pattern> but you are hitting /com.x.maps.maps.Maps instead. Hence you are getting the 404 path not found status code.
Alter the url-pattern on the server-side web.xml to match what the browser is making,
OR
Alter the GWT code using the RemoteServiceRelativePath annotation to make the request to /Maps/service instead of to /com.x.maps.maps.Maps
I have had the same problem but I solved it changing the url-pattern of the Servlet in the web.xml
Try to put in your web.xml the path to the directory where your GWT javascript module is generated, behind WEB-INF/deploy. in my case:
<url-pattern>/gwtmodulemain/selection</url-pattern>
You can also rename your module name in your gwt.xml file:
<module rename-to='gwtmodulemain'>
so you can refer your module from your HTML in this way:
<script type="text/javascript" language="javascript" src="gwtmodulemain/gwtmodulemain.nocache.js"></script>
Good luck!