I'm trying to invoke a Ruby method from Java using the example code from:
https://github.com/tc/call-jruby-from-java-example
Here is what the java code looks with the embedded Ruby script:
#Service
public class ProcessorImpl extends RubyObject implements IProcessor {
private static final Ruby __ruby__ = Ruby.getGlobalRuntime();
private static final RubyClass __metaclass__;
static {
String source = new StringBuilder(
"require 'java'\n" +
"require 'resque'\n" +
"\n" +
"class SaveData\n" +
" #queue = :general\n" +
"end\n" +
" \n" +
"class JRubyResqueImpl\n" +
" include Java::IProcessor\n" +
" \n" +
" java_signature 'void enqueue( Object )'\n" +
" def enqueue( data )\n" +
" Resque.enqueue( SaveData, data )\n" +
" end\n" +
"end\n" +
"").toString();
__ruby__.executeScript(source, "JRubyResqueImpl.rb");
RubyClass metaclass = __ruby__.getClass("JRubyResqueImpl");
metaclass.setRubyStaticAllocator(ActProcessorImpl.class);
__metaclass__ = metaclass;
}
public ActProcessorImpl(Ruby runtime, RubyClass metaClass)
{
super(runtime, metaClass);
}
public static IRubyObject __allocate__(Ruby ruby, RubyClass metaClass)
{
return new ActProcessorImpl(ruby, metaClass);
}
public ActProcessorImpl()
{
this(__ruby__, __metaclass__);
}
#Override
public void enqueue(Object obj)
{
ObjectMapper mapper = new ObjectMapper();
OutputStream os = new ByteArrayOutputStream();
try {
mapper.writeValue(os, obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
String json = os.toString();
IRubyObject rbJson = JavaUtil.convertJavaToRuby(__ruby__, json);
RuntimeHelpers.invoke(__ruby__.getCurrentContext(), this, "enqueue",rbJson);
}
}
When the Spring Framework IoC module is doing the autowiring it tries to instantiate this class which fails with the following error message:
org.jruby.exceptions.RaiseException: (LoadError) no such file to load -- resque
I don't see any errors when I take the embedded Ruby script and run it via the CLI using the command:
jruby -S JRubyResqueImpl.rb
Where the content of JRubyResqueImpl.rb is:
require 'java'
require 'resque'
class SaveData
#queue = :general
end
class JRubyResqueImpl
include Java::IProcessor
java_signature 'void enqueue( Object )'
def enqueue( data )
Resque.enqueue( SaveData, data )
end
end
I've configured the environment variables GEM_HOME, GEM_PATH and set JRUBY_OPTS=--1.9.
Using Oracle Java 1.6.0_25, JRuby 1.6.4 and Resque 1.19.0 running under Ubuntu 11.10.
Thanks in advance.
I was able to make some progress by explicitly loading the dependencies in the embedded ruby script like so:
//java code
String source = new StringBuilder(
"require 'java'\n" +
"load '/usr/local/jruby/jruby-1.6.4/lib/ruby/1.9/singleton.rb'\n" +
"load '/usr/local/jruby/jruby-1.6.4/lib/ruby/gems/gems/monitor-0.1.3/lib/monitor/controller.rb'\n" +
"load '/usr/local/jruby/jruby-1.6.4/lib/ruby/gems/gems/monitor-0.1.3/lib/monitor.rb'\n" +
"load'/usr/local/jruby/jruby-1.6.4/lib/ruby/gems/redis-2.2.2/lib/redis.rb'\n" +
"load '/usr/local/jruby/jruby-1.6.4/lib/ruby/gems/redis-namespace-1.0.3/lib/redis-namespace.rb'\n" +
"load '/usr/local/jruby/jruby-1.6.4/lib/ruby/gems/resque-1.19.0/lib/resque.rb'\n" +
"\n" +
etc...
But now I see the following error from Spring IoC:
org.jruby.exceptions.RaiseException: (LoadError) no such file to load -- singleton
Still stuck...
Related
I'm setting up my Pepper-Box Plain text Config to Pass variable using ${accountNumber}, ${{accountNumber}}, {{accountNumber}}, and using function to return string, but it didn't work.
This is my message to kafka :
{
"eventName": "OFFER",
"payload": {
"accountNumber": "${accountNumber}",
"Limit": 20000000
}
}
but the variable didn't pass, when I see the debug sampler, the accountNumber is pass.
I think there is mistake when I call the variable, but I try some techniques but it didnt work too.
The error Message when I try ${{accountNumber}} is :
symbol: method accountNumber()
location: class MessageIterator1566802574812
1 error
Uncaught Exception java.lang.ClassFormatError: Truncated class file. See log file for details.
It looks like a limitation of the plugin, you're basically limited to Schema Template Functions
Alternatively you can send a record to Kafka using JSR223 Sampler and the following Groovy code:
import org.apache.jmeter.threads.JMeterVariables
import org.apache.kafka.clients.producer.KafkaProducer
import org.apache.kafka.clients.producer.ProducerRecord
def kafkaProps = new Properties()
kafkaProps.put(org.apache.kafka.clients.producer.ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092")
kafkaProps.put(org.apache.kafka.clients.producer.ProducerConfig.CLIENT_ID_CONFIG, "KafkaExampleProducer")
kafkaProps.put(org.apache.kafka.clients.producer.ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, org.apache.kafka.common.serialization.LongSerializer.class.getName())
kafkaProps.put(org.apache.kafka.clients.producer.ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, org.apache.kafka.common.serialization.StringSerializer.class.getName())
def producer = new KafkaProducer<>(kafkaProps)
JMeterVariables vars = new JMeterVariables()
vars.put("accountNumber", "foo")
def record = new ProducerRecord<>("test", "{\n" +
" \"eventName\": \"OFFER\",\n" +
" \"payload\": {\n" +
" \"accountNumber\": \"" + vars.get("accountNumber") + "\",\n" +
" \"Limit\": 20000000\n" +
" }\n" +
"}")
producer.send(record)
More information: Apache Kafka - How to Load Test with JMeter
I have taken a written sample from this link to write my Python + Java integration code.
http://www.jython.org/jythonbook/en/1.0/JythonAndJavaIntegration.html
The code looks like below.
package org.jython.book.interfaces;
import org.jython.book.interfaces.JythonObjectFactory;
import org.python.core.Py;
import org.python.core.PyString;
import org.python.core.PySystemState;
public class Main {
public static void main(String args[]) {
String projDir = System.getProperty("user.dir");
String rootPath = projDir + "/src/org/jython/book/interfaces/";
String modulesDir = projDir + "/src/org/jython/book/interfaces/";
System.out.println("Project dir: " + projDir);
PySystemState sysSt = Py.getSystemState();
JythonObjectFactory factory = new JythonObjectFactory(sysSt, BuildingType.class, "Building", "Building");
BuildingType building = (BuildingType) factory.createObject();
building.setBuildingName("BUIDING-A");
building.setBuildingAddress("100 MAIN ST.");
building.setBuildingId(1);
System.out.println(building.getBuildingId() + " " +
building.getBuildingName() + " " +
building.getBuildingAddress());
}
}
When I run this code, it throws an error that it did not find the python module. I have kept the .py and .pyc files under the path provided as 'modulesDir'.
The literature says that "the requested module must be contained somewhere on the sys.path"; however, I did not understand how this can be set from this Java program. Can someone please provide some help?
Project dir: /Users/eclipsews/PythonJava
Exception in thread "main" ImportError: No module named Building
Hi found the answer to this issue!
Added the PySystemState.initialize method where I explicitly provide the "python.path" property, which is initialized to my project's path, where python modules are available.
private static Properties setDefaultPythonPath(Properties props) {
String pythonPathProp = props.getProperty("python.path");
String new_value;
if (pythonPathProp == null) {
new_value = System.getProperty("user.dir") + "/src/org/jython/book/interfaces/";
}
props.setProperty("python.path", new_value);
return props;
}
Properties props = setDefaultPythonPath(System.getProperties());
PySystemState.initialize( System.getProperties(), props, null );
This produces the correct output as follows:
module=<module 'Building' from '/Users/eclipsews/PythonJava/src/org/jython/book/interfaces/Building$py.class'>,class=<class 'Building.Buildin
g'>
1 BUIDING-A 100 MAIN ST.
I've written a method for pushing real-time location data to Firebase:
private void writeNewMarker(int sessionType, String myUuid, String datetime, Location location) {
locationToDB = new LocationFromAndroid();
JSONObject jsonObjectCoords = new Coords(location.getLatitude() + "", location.getLongitude() + "", location.getAltitude() + "");
locationToDB.setFinish("false");
locationToDB.setLost("false");
locationToDB.setCoords(jsonObjectCoords);
locationToDB.setDistanceToGo("0");
locationToDB.setHeading(location.getBearing() + "");
locationToDB.setNauwkeurigheid(location.getAccuracy() + "");
locationToDB.setSpeed(location.getSpeed() * 3.6 + "");
locationToDB.setSpeed2(location.getSpeed() + "");
locationToDB.setTimestamp(location.getTime() + "");
locationToDB.setWp_user(myUuid);
locationToDB.setSessionType(sessionType);
locationToDB.setTitle(title);
if(myUuid != null && datetime != null && locationToDB.getTitle() != null && !myUuid.isEmpty() && !datetime.isEmpty()) {
databaseRef.child(myUuid + "-Android" + sessionType + datetime).setValue(locationToDB);
When I'm building the app in debug mode, it works perfectly fine. But when I'm building it in Release mode for Google Play, it stops working at this line:
databaseRef.child(myUuid + "-Android" + sessionType + datetime).setValue(locationToDB);
To be more specific: When I'm doing this, everything is OK:
databaseRef.child(myUuid + "-Android" + sessionType + datetime).setValue("Test");
It does look like passing an object as value isn't possible within a signed APK?
Error:
Exception com.google.firebase.database.DatabaseException: No properties to serialize found on class
Adding -keepclassmembers class com.yourcompany.models.** { *; } in proguard-rules.pro did the trick.
Proguard Rules Documentation
Code -
private static String getDBInstanceTag(AmazonRDS amazonRDS, String dbInstanceIdentifier, String region, String tagKey) {
log.info("Trying to fetch dbInstanceIdentifier - " + dbInstanceIdentifier + " in db instance region - " + region);
String arn = String.format("arn:aws:rds:" + region + ":%s:db:%s",
SyncJobConstants.AWSProperties.AWS_ACCOUNT_NUMBER,
dbInstanceIdentifier);
ListTagsForResourceResult tagsList = amazonRDS.listTagsForResource(
new ListTagsForResourceRequest().withResourceName(arn));
for(Tag tag : tagsList.getTagList()) {
if(tagKey.equalsIgnoreCase(tag.getKey())) {
return tag.getValue();
}
}
throw new InternalProcessingException(tagKey + " is not present in given dbInstance - " + tagsList);
}
public static String getDBInstanceTag(String dbInstanceIdentifier, String tagKey) throws IOException {
AWSCredentials credentials = new PropertiesCredentials(
RedshiftUtil.class.getClassLoader().getResourceAsStream("AWSCredentials.properties"));
AmazonRDS amazonRDS = new AmazonRDSClient(credentials);
DBInstance dbInstance = new DBInstance();
dbInstance.setDBInstanceIdentifier(dbInstanceIdentifier);
for(String region : SyncJobConstants.AWSProperties.RDS_REGIONS) {
try {
return getDBInstanceTag(amazonRDS, dbInstanceIdentifier, region, tagKey);
} catch (DBInstanceNotFoundException e) {
log.info("dbInstanceIdentifier - " + dbInstanceIdentifier + " is not present in db instance region - " + region);
} catch (AmazonServiceException e) {
if ( "AccessDenied".equals(e.getErrorCode()) ) {
log.info("dbInstanceIdentifier - " + dbInstanceIdentifier + " is not present in db instance region - " + region);
} else {
throw new InternalProcessingException("Not able to fetch dbInstance details from RDS. DBInstanceId - " + dbInstanceIdentifier, e);
}
}
}
throw new InvalidRequestException("RDS endpoint details is not correct.");
}
It is throwing error for some of the calls even though db instances is there. Error detail -
Caused by: com.amazonaws.AmazonServiceException: The specified resource name does not match an RDS resource in this region. (Service: AmazonRDS; Status Code: 400; Error Code: InvalidParameterValue; Request ID: b0e01d56-36ca-11e6-8441-1968d9061f57)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1182)
at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:770)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:489)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:310)
at com.amazonaws.services.rds.AmazonRDSClient.invoke(AmazonRDSClient.java:5197)
at com.amazonaws.services.rds.AmazonRDSClient.listTagsForResource(AmazonRDSClient.java:1997)
Can you please tell me what I am missing here ?
Error meanings-
http://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html
Update 2
public static final List RDS_REGIONS = Arrays.asList("us-east-1",
"us-west-1",
"us-west-2",
"eu-west-1",
"eu-central-1",
"ap-northeast-1",
"ap-northeast-2",
"ap-southeast-1",
"ap-southeast-2",
"sa-east-1");
Seems like a region related issue - Is your RDS instance located in region US-EAST-1? (that's the default region of Amazon SDK)
Log into Amazon web console and confirm the region. Set the correct region and try again.
Reference : AWS Region Selection
Although this is an old question, I am sharing an idea that might help someone..
As it seems the user is using a Java AWS SDK client, he can use describeDBInstances on the
AmazonRDS amazonRDS = new AmazonRDSClient(credentials);
DescribeDBInstancesResult describeDBInstancesResult = amazonRDS.describeDBInstances();
then you can debug and look into the describeDBInstancesResult to make sure that DB is actually within the scope of current instantiated amazonRDS client.
if its not there, it might be that he using not passing the right region into the client.
Does anyone know how to modify the Jenkins/Hudson node labels in a non-manually way? I mean, thorough an API like the CLI API that this tool offers (without restarting Jenkins/Hudson of course).
My guess is that the best option is using a Groovy script to enter into the Jenkins/Hudson guts. Executing something like:
java -jar -s HUDSON_URL:8080 groovy /path/to/groovy.groovy
Being the content of that script something like:
for (aSlave in hudson.model.Hudson.instance.slaves) {
labels = aSlave.getAssignedLabels()
println labels
**aSlave.setLabel("blabla")** // this method doesn't exist, is there any other way???
}
Thanks in advance!
Victor
Note: the other answers are a bit old, so it could be that the API has appeared since then.
Node labels are accessed in the API as a single string, just like in the Configure screen.
To read and write labels: Node.getLabelString() and Node.setLabelString(String).
Note that you can get the effective labels as well via: Node.getAssignedLabels(), which returns a Collection of LabelAtom that includes dynamically computed labels such as the 'self-label' (representing the node name itself).
Last, these methods on the Node class are directly accessible from the slave objects also, e.g. as a System Groovy Script:
hudson = hudson.model.Hudson.instance
hudson.slaves.findAll { it.nodeName.equals("slave4") }.each { slave ->
print "Slave $slave.nodeName : Labels: $slave.labelString"
slave.labelString = slave.labelString + " " + "offline"
println " --> New labels: $slave.labelString"
}
hudson.save()
I've found a way to do this using the Groovy Postbuild Plugin.
I have a Jenkins job that takes a few parameters (NodeToUpdate, LabelName, DesiredState) and executes this content in the Groovy Postbuild Plugin:
nodeName = manager.envVars['NodeToUpdate']
labelName = manager.envVars['LabelName']
set = manager.envVars['DesiredState']
for (node in jenkins.model.Jenkins.instance.nodes) {
if (node.getNodeName().equals(nodeName)) {
manager.listener.logger.println("Found node to update: " + nodeName)
oldLabelString = node.getLabelString()
if (set.equals('true')) {
if (!oldLabelString.contains(labelName)) {
manager.listener.logger.println("Adding label '" + labelName + "' from node " + nodeName);
newLabelString = oldLabelString + " " + labelName
node.setLabelString(newLabelString)
node.save()
} else {
manager.listener.logger.println("Label '" + labelName + "' already exists on node " + nodeName)
}
}
else {
if (oldLabelString.contains(labelName)) {
manager.listener.logger.println("Removing label '" + labelName + "' from node " + nodeName)
newLabelString = oldLabelString.replaceAll(labelName, "")
node.setLabelString(newLabelString)
node.save()
} else {
manager.listener.logger.println("Label '" + labelName + "' doesn't exist on node " + nodeName)
}
}
}
}
I've not seen a way yet to change the slave label either.
I've taken to editing the main config.xml file and issuing a reload from the CLI.
This has it's own problems though - any jobs currently running are lost until the next jenkins restart - see https://issues.jenkins-ci.org/browse/JENKINS-3265