I ran into the following Java compiler warning issue (using IntelliJ 14):
I have the following class in my Scala library:
object ScalatoJava {
def asJava[A,B](map: Map[A,B]): java.util.Map[A,B] = { map.asJava }
def asJava[A](list: List[A]): java.util.Collection[A] = {list.asJavaCollection}
}
I use it to convert few collections coming from Scala in my Java program.
Now in my Java program I have the following code for which IntelliJ is underlying in red stating that it can't resolve things:
private final java.util.Map<String, FieldSettings> poolpartyfieldsettings =
ScalatoJava.asJava(poolpartyConnectorSettings.fieldsSettingsMap());
It says it can not resolve the method asJava(scala.collection.immutable.Map<String, org.....FieldSettings>).
While if I write either
private final java.util.Map <String, FieldSettings> poolpartyfieldsettings =
ScalatoJava.asJava((scala.collection.immutable.Map<String, FieldSettings>)poolpartyConnectorSettings.fieldsSettingsMap());
or
scala.collection.immutable.Map<String, FieldSettings> poolpartyfieldsettings =
poolpartyConnectorSettings.fieldsSettingsMap();
ScalatoJava.asJava(poolpartyfieldsettings)
the compiler does not complain.
Here is the PoolpartyConnectorSettings Scala class:
trait DspacePoolPartyConnectorSettings {
def poolpartyServerSettings : PoolpartySettings
def fieldsSettingsList : List[FieldSettings]
def fieldsSettingsMap : Map[String, FieldSettings]
}
case class DspaceDspacePoolPartyConnectorSettingImpl (configUri: String) extends DspacePoolPartyConnectorSettings {
private val config = ConfigFactory.parseURL(new URL(configUri)).resolve()
private val configFieldSettinglist = config.getConfigList("PoolPartyConnectorSettings.FieldSettings").asScala.toList
private val configPoolPartySetting = config.getConfig("PoolPartyConnectorSettings.PoolPartySettings")
val poolpartyServerSettings = PoolpartySettings( configPoolPartySetting.getString("apirootEndpoint"),
configPoolPartySetting.getString("thesaurusapiEndpoint"),
configPoolPartySetting.getString("extratorapiEndpoint"),
configPoolPartySetting.getString("coreProjectId"),
configPoolPartySetting.getString("coreThesaurusUri"),
configPoolPartySetting.getString("jelProjectId"),
configPoolPartySetting.getString("jelThesaurusUri"))
val fieldsSettingsList = configFieldSettinglist map { e =>
FieldSettings(e.getString("fieldname"), e.getBoolean("treeBrowser"),
e.getBoolean("multilanguage"), e.getStringList("languages").asScala.toList,
e.getBoolean("closed"), e.getString("scheme"), e.getString("poolpartyProjectId"))
}
val fieldsSettingsMap = Map(fieldsSettingsList map {e => (e.fieldName, e)}: _*)
}
Any idea what the problem might be?
Related
spark.sqlContext.udf.register('dataSource', (data: scala.collection.mutable.WrappedArray$ofRef, ofType : String) => {
var flag = ''
try{
val array: Seq[String] = data.flatten(x => Seq(x.toString()))
array.foreach(s => if(s.contains(ofType)) { flag = ofType })
}
catch {
println("Exception :" + x.getMessage)
flag = ''
}
flag;
})
It is not required to convert this Scala code into Java code. In Spark you can register a UDF in any of the languages and also make use of it in either Java or Scala as long as it is used in the same SparkSession or Context.
I came across a use-case where I need to update a specific field in the ElasticSearch document. So for this use-case, I have used the Update API with a script ES doc. But I faced an issue(compilation error) with Script Constructor which accepts the following parameters:--> type, lang, idOrCode and params and the issue was with params(java.util.Map) parameter.
I have even tried the Scala to Java converters but could not solve it.
Code snippet
import org.elasticsearch.action.update.UpdateRequest
import org.elasticsearch.client.RequestOptions
import org.elasticsearch.script.{Script, ScriptType}
object Testing extends App {
val result = updateByScript("testing", "hW7BBnQBn2nWmIjS_b0C", 10.0)
println("######result:---> " + result)
high_level_client.close()
def updateByScript(index: String, id: String, count: Double) = {
//import scala.collection.JavaConversions.mapAsJavaMap
//import collection.JavaConverters._
import scala.collection.JavaConverters._
val updateRequest = new UpdateRequest(index, id)
val params = Map[String, Double]("count" -> count)
val script = new Script(ScriptType.INLINE, "painless", "ctx._source.count += params.count", mapAsJavaMap(params))
updateRequest.script(script)
high_level_client.update(updateRequest, RequestOptions.DEFAULT)
}
}
For the above issue, I have tried the Script Constructor with the idOrCode parameter and which solved my use-case but still I did not get the solution for other Script Constructors.
Working code with Constructor which accept idOrCode parameter.
Code snippet
import org.elasticsearch.action.update.UpdateRequest
import org.elasticsearch.client.RequestOptions
import org.elasticsearch.script.{Script, ScriptType}
object Testing extends App {
val result = updateByScript("testing", "hW7BBnQBn2nWmIjS_b0C", 10.0)
println("######result:---> " + result)
high_level_client.close()
def updateByScript(index: String, id: String, count: Double) = {
val updateRequest = new UpdateRequest(index, id)
val script = new Script(s"""ctx._source.count += $count""")
updateRequest.script(script)
high_level_client.update(updateRequest, RequestOptions.DEFAULT)
}
}
I'm trying to send a PythonJavaClass (NokeServiceListener) into mNokeService.registerNokeListener() but it keeps erroring out there and when printing the NokeServiceListener object I'm getting nokeLock.NokeServiceListener object at 0x97389b70 which doesn't look like a java object and then I get an error JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0x6e617278
from jnius import autoclass,PythonJavaClass,cast,java_method
Context = autoclass('android.content.Context')
Parcelable = autoclass('android.os.Parcelable')
Intent = autoclass('android.content.Intent')
Uri = autoclass('android.net.Uri')
PythonActivity = autoclass('org.kivy.android.PythonActivity')
NokeDeviceManagerService = autoclass('com.noke.nokemobilelibrary.NokeDeviceManagerService')
#LocalBinder = autoclass('com.noke.nokemobilelibrary.NokeDeviceManagerService$LocalBinder')
NokeDevice = autoclass('com.noke.nokemobilelibrary.NokeDevice')
NokeMobileError = autoclass('com.noke.nokemobilelibrary.NokeMobileError')
#NokeServiceListener =autoclass('com.noke.nokemobilelibrary.NokeServiceListener')
global mNokeService
##run_on_ui_thread
class NokeApi():
def __init__(self):
self.python_activity = PythonActivity.mActivity
self.service_connection = ServiceConnection()
def initiateNokeService(self):
currentActivity = cast('android.app.Activity', self.python_activity)
context = cast('android.content.Context', currentActivity.getApplicationContext())
nokeIntent = Intent()
nokeIntent.setClassName(context, 'com.noke.nokemobilelibrary.NokeDeviceManagerService')
self.python_activity.bindService(nokeIntent,self.service_connection,Context.BIND_AUTO_CREATE)
def onCreate(self):
self.initiateNokeService()
##run_on_ui_thread
class ServiceConnection(PythonJavaClass):
__javainterfaces__ = ['android.content.ServiceConnection']
__javacontext__ = 'app'
#java_method('(Landroid/content/ComponentName;Landroid/os/IBinder;)V')
def onServiceConnected(self,className, rawBinder):
print 'debug1'
#nokeDeviceManagerService = NokeDeviceManagerService()
#localBinder = LocalBinder()
nokeService = cast('com.noke.nokemobilelibrary.NokeDeviceManagerService$LocalBinder',rawBinder)
global mNokeService
mNokeService = nokeService.getService()
print mNokeService
#mNokeService = ((NokeDeviceManagerService.LocalBinder)rawBinder).getService()
print 'debug2'
mNokeServiceListener = NokeServiceListener()
#mNokeServiceListener = cast('com.noke.nokemobilelibrary.NokeServiceListener',nokeServiceListener)
print mNokeServiceListener
print 'debug2.5'
mNokeService.registerNokeListener(mNokeServiceListener)
print 'debug3'
noke1 = NokeDevice("NOKE3P", "F7:F3:F1:2C:66:25")
print 'debug4'
mNokeService.addNokeDevice(noke1)
print 'debug5'
mNokeService.setUploadUrl("https://coreapi-sandbox.appspot.com/upload/")
print 'debug6'
mNokeService.startScanningForNokeDevices()
print "Scanning for devices"
if not mNokeService.initialize():
print "Unable to initialize Bluetooth"
class NokeServiceListener(PythonJavaClass):
__javainterfaces__ = ['com.noke.nokemobilelibrary.NokeServiceListener']
__javacontext__ = 'app'
def __init__(self):
pass
#java_method('(Lcom/noke/nokemobilelibrary/NokeDevice;)V')
def onNokeDiscovered(self,noke):
print "Connecting to Noke"
mNokeService.connectToNoke(self,noke)
#java_method('(Lcom/noke/nokemobilelibrary/NokeDevice;)V')
def onNokeConnecting(self,noke):
print "Connecting"
#java_method('(Lcom/noke/nokemobilelibrary/NokeDevice;)V')
def onNokeConnected(self,noke):
print "Noke Connected"
self.requestUnlock(noke)
#java_method('(Lcom/noke/nokemobilelibrary/NokeDevice;)V')
def onNokeSyncing(self,noke):
print "NOKE SYNCING"
#java_method('(Lcom/noke/nokemobilelibrary/NokeDevice;)V')
def onNokeUnlocked(self,noke):
print 'Noke Unlocked'
#java_method('(Lcom/noke/nokemobilelibrary/NokeDevice;)V')
def onNokeDisconnected(self,noke):
print "Noke Disconnected"
self.mNokeService.uploadData()
self.mNokeService.startScanningForNokeDevices()
#java_method('(I)V')
def onBluetoothStatusChanged(self,bluetoothStatus):
pass
#java_method('(Lcom/noke/nokemobilelibrary/NokeDevice;ILjava/lang/String;)V')
def onError(self,noke, error, message):
pass
def requestUnlock(self,noke):
msg = '{"function":"Noke_Unlock","session":"%s","mac":"%s"}' % (noke.getSession(),noke.getMac())
rsp = connectToServer(_host, _port, msg)
if rsp['result'] == "success":
commandStr = rsp["commands"]
noke.sendCommands(commandStr)
else:
print "Access Denied"
I feel like there error is because I'm passing in a non java object into a java function but I've already tried to cast the object as a 'com.noke.nokemobilelibrary.NokeServiceListener' and that didn't work either. The code always errors out after debug 2.5 so something is going wrong between those two steps but I can't figure out what.
class NokeServiceListener(PythonJavaClass):
def __init__(self, callback):
super().__init__()
self.callback = callback
It will work because python is not java / C#. base class init will not called unless you explicitly write it.
Adding
class NokeServiceListener(PythonJavaClass):
def __init__(self, callback):
super(NokeServiceListener, self).__init__()
self.callback = callback
seemed to fix this issue... no idea why though.
I am using the datastax java drver for Cassandra from scala (2.10.4)
to build batches of prepared statements
but have hit the following problem.
Table definition in CQL
use ks;
drop table bc_test;
create table bc_test(
id TEXT,
id_1 BIGINT,
c1 COUNTER,
c2 COUNTER,
PRIMARY KEY(id, id_1)
);
First problem is implicit numeric widening error
import com.datastax.driver.core.{ResultSet, ProtocolOptions, Cluster, Session}
import com.datastax.driver.core.RegularStatement
import com.datastax.driver.core.PreparedStatement
import com.datastax.driver.core.BoundStatement
import com.datastax.driver.core.BatchStatement
val c = Cluster.builder().addContactPoint("127.0.0.1").withPort(9042).build
val sess = c.connect("ks")
val p_bc_test_c1: PreparedStatement =
sess.prepare("UPDATE bc_test SET c1 = c1 + ? WHERE id = ? and id_1 = ?")
val batch: BatchStatement = new BatchStatement(BatchStatement.Type.COUNTER);
val id1: Long = 1L
val idText: String = "one"
val c1: Long = 1L
batch.add(p_bc_test_c1.bind(c1, "one", id1))
// which gives the error
scala> batch.add(p_bc_test_c1.bind(c1, "one", id1))
<console>:19: error: implicit numeric widening
batch.add(p_bc_test_c1.bind(c1, "one", id1))
^
I can get around this using type ascription but wanted to find something a bit nicer
that can also be built into a more generic solution. What I came up with was :
import scalaz._
import Scalaz._
import shapeless._
import poly._
import syntax.std.tuple._
trait CassandraLongVal
type CassandraLong = java.lang.Long ## CassandraLongVal
def cassandraLongCol(c : Long): CassandraLong = Tag(c)
trait CassandraIntVal
type CassandraInt = java.lang.Integer ## CassandraIntVal
def cassandraIntCol(c : Int): CassandraInt = Tag(c)
object ToCassandraType extends Poly1 {
implicit def caseInt = at[Int](cassandraIntCol(_))
implicit def caseLong = at[Long](cassandraLongCol(_))
implicit def caseString = at[String](identity)
}
case class Update1(cval: Long, id: String, id1: Long)
val update1Gen = Generic[Update1]
val bUpdate1 = Update1(125L, "two", 1L)
val update1AsArray = update1Gen.to(bUpdate1).map(ToCassandraType).toArray
batch.add(p_bc_test_c1.bind(update1AsArray:_*))
batch.add(p_bc_test_c1.bind(update1AsArray:_*))
sess.execute(batch)
This seems to work quite happily and I can use the basic pattern for dozens of table with different columns.
Is this a reasonable approach, or is there a simpler way to get the same outcome whilst trying to keep a handle on the types
and am I abusing scalaz/ shapeless through my (considerable) ignorance.
Can anyone assist me on how do I load the object FooBar dynamically and call the roquet function (dynamically) ?
I have this snippet in Perl:
#!/usr/bin/perl -w
use Inline Java => << 'End_Of_Java_Code';
class FooBar {
public FooBar(){}
public void roquet() {
System.out.println("HELLO!");
}
}
End_Of_Java_Code
use Data::Dumper;
use Class::Sniff;
my $sniff = Class::Sniff->new({class=>'FooBar'});
my $num_methods = $sniff->methods;
my $num_classes = $sniff->classes;
my #methods = $sniff->methods;
my #classes = $sniff->classes;
my #unreachable = $sniff->unreachable;
foreach my $method (#methods) {
if ( $method eq "roquet" ) {
print "$method\n";
}
}
I tried the following approaches and variations:
a. approach:
use Module::Load
my $package = "main::FooBar";
load $package;
$package->new();
$package->$rflmethod;//where rflmethod is the variable: $rflmethod='roquet';
b. approach:
no strict 'refs';
use Package::Stash;
my $stash = Package::Stash->new('main::FooBar');
my $coderef = $stash->get_symbol('&__new');
$coderef->()
This works:
my ($class, $method) = qw(FooBar roquet);
my $f = $class->new;
$f->$method;