I am trying to convert some Java Spring components into Kotlin, and I tried using the Intellij Convert to Kotlin feature.
The code converted in Kotlin is just fine, no errors, I checked the logic and there is no issue there.
The problem is that any kind of #Component I am trying to convert, it gives me a confusing error.
The error:
e: java.io.IOException: java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 0
The Kotlin Component:
#Component
class Component {
#Autowired
private val service: Service? = null
// Service class also in Kotlin, works just fine
// ...
}
Java code:
#Component
public class Component {
#Autowired
private Service service;
// Service class in Kotlin, works just fine
// ...
}
I have also tried with having the component as an open class, but the same error came up.
Related
I have this configuration class in two different kotlin projects.
In one it works just fine. In the other one, I get an error and I am asked to make the class open, and when I run the program, the bean cannot be found.
I am really confused as the same configuration seems to be working fine in a different project. Could you please suggest a way that would allow me to avoid making the class open, as I dont see the reason for doing so since in the other project I did not have to, or a reason why the bean cannot be found?
#Configuration
#ComponentScan(value = ["com.bank.manager"])
#PropertySources(PropertySource("classpath:application.yml"),
PropertySource(value = ["file:\${bank.target.config}"]))
class BankInstanceConfig(#Autowired private val env: Environment) {
#Bean fun bankInstance(): List<String> {
return env.getRequiredProperty("bank-instance").toString().split("#")
}
}
Then on class level I define the bean like this:
#Service
class BankDiscoveryServiceImpl(#Autowired bankInstance: BankInstanceConfig) {}
I want to write a clojure lib and exposes generated classes, so that other java projects could use it.
I read and followed the gen-class doc, and everything works as my expect, except class annotation with enum parameters.
(ns common.exception.unauthorized
(:gen-class :name
^{org.springframework.web.bind.annotation.ResponseStatus
org.springframework.http.HttpStatus/UNAUTHORIZED} ; <- here
com.lalala.common.exception.Unauthorized
:extends java.lang.RuntimeException
:init init
:constructors {[String] [String]}
:main false
:prefix "unauthorized-"))
(defn unauthorized-init [^String message]
[[message] nil])
This exception class is generated without any error, and it also able be used as an Exception. However, this exception is intended to be used as a http response along with spring web. The spring framework read the annotation, and find that it is HttpStatus/UNAUTHORIZED then response 401. But the spring framework throws exception complaining that java.lang.EnumConstantNotPresentException: org.springframework.http.HttpStatus.
And I had a look at the generated class, it's something like this:
#ResponseStatus(HttpStatus.401)
public class Unauthorized extends RuntimeException {
private static final Var init__var = Var.internPrivate("common.exception.unauthorized", "unauthorized-init");
private static final Var getStackTrace__var = Var.internPrivate("common.exception.unauthorized", "unauthorized-getStackTrace");
// ...... ellipsis
}
As it shown, the HttpStatus/UNAUTHORIZED is compiled into HttpStatus.401 which is invalid.
I also tried with {:code org.springframework.http.HttpStatus/UNAUTHORIZED}, {:value org.springframework.http.HttpStatus/UNAUTHORIZED}, it can be compiled into #ResponseStatus(code/value = HttpStatus.401), but the enum value itself still in invalid form HttpStatus.401.
Am I use class annotation for gen-class in a wrong way? or just Clojure compiler just have this bug?
P.S. tried with Clojure 1.9, 1.10, 1.10.1
Finally, I use native Java code instead. I realized that writing classes in clojure with only ctor forwarded to super class is making trouble for myself.
I embedded java code in the project along with :java-source-paths configured in defproject, got my problem solved.
Recently I am using play 2.4 framework for Java project.
In that I am using WsClient Library. That library is injected in my class.
#Inject WSClient wsClient
Now I am trying to write a test case for that class but test case fails because of null pointer error for wsClient variable.
wsClient.url("some url").get()
Can you please help me to resolve this?
following is the test code
// Class
public class ElasticSearch {
#Inject WSClient wsClient;
public Promise<WSResponse> createIndex() {
Logger.info("Entering ElasticSearch.createIndex()");
Logger.debug("WSClient: " + wsClient);
Promise<WSResponse> response =wsClient.url(this.getEsClient()+ "/" +this.getEsIndexName()).setContentType("application/json").put("");
Logger.info("Exiting ElasticSearch.createIndex()");
return response;
}
}
// Test function
#Test
public void testCreateIndex() {
running(fakeApplication(), new Runnable() {
public void run() {
ElasticSearch esearch= new ElasticSearch();
esearch.setEsIndexName("car_model");
assertNotNull(esearch.createIndex());
}
});
}
Before writing the options you have, I suggest to use elastic4s.
This third party lib will help you write a more functional code and give you very nice dsl to write your queries.
One more thing, I don't know what is your used case for using elasticsearch, but I recommend using a different client then the rest api, which will give you more secure connection and more efficient.
You get the NPE, because you instasiate ElasticSearch by your own with new, and don't let guice to the wiring for you, this is why the WSClient is null.
Now for your options,
You have 2 options:
Add WithApplication to your test, which will basically load your application, this will give you the access to Guice injector, from which you can take ElasticSearch class like this you have couple of ways to do it:
As described in play documentation using
import play.api.inject.guice.GuiceInjectorBuilder
import play.api.inject.bind
val injector = new GuiceInjectorBuilder()
.configure("key" -> "value")
.bindings(new ComponentModule)
.overrides(bind[Component].to[MockComponent])
.injector
val elasticsearch = injector.instanceOf[ElasticSearch]
By importing Play
import play.api.Play
val elasticsearch = Play.current.injector.instanceOf(classOf[ElasticSearch])
Using FakeApplication: just get hold of the fake application injector, and use it to get an instance of ElasticSearch class.
I don't like the above options, because you need an application running, which can make your tests very slow.
I suggest to create the WSClient by your self and instantiate ElasticSearch class with it, and run your tests.
val httpClient = NingWSClient.apply()
val elasticsearch = new ElasticSearch(httpClient)
This is a more light solution, and should make your tests run faster.
I'm writing Google Endpoints application and I want to return protobuf object in my #Api class.
All the time I'm getting this error:
Error:Gradle: Execution failed for task ':ExploreBackend:appengineEndpointsGetClientLibs'.
There was an error running endpoints command get-client-lib: Object type ? extends xxx.model.proto.MainProtos$PlaceOrBuilder not supported.
This is my code:
#Api( ... )
public class CityApi {
public List<MainProto.City> getCities() {
return new ArrayList<MainProto.City>();
}
}
How to use protobuf in google endpoints
You can not
i have a grails application and i'm following the tutorial here:
http://www.grails.org/Services
i have some code like
import org.springframework.beans.factory.InitializingBean
class SubmitRequestService implements InitializingBean{
def GrailsApplication1
def setting
void afterPropertiesSet(){
this.setting = GrailsApplication1.config.setting
}
def void sendHistoricalContract(HistoricalContract hc_instance){
//... blah blah whatever code
}
}
class SubmitRequestController {
def submitRequestService
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def index = {
// .... blah blah whatever code
submitRequestService.sendHistoricalContract(historicalContractInstance)
}
}
No whatever i do, i can't seem to get the service to be injected into the controller. Whenever I get to the line where i call the service i get the error:
ERROR errors.GrailsExceptionResolver - Cannot invoke method sendHistoricalContract() on null object
What am i doing wrong?
Thanks in advance
GrailsApplication1 looks weird - what's that coming from? If you want to access the GrailsApplication instance to get to the config, use a dependency injection for the grailsApplication Spring bean:
class SubmitRequestService implements InitializingBean {
private setting
def grailsApplication
void afterPropertiesSet() {
setting = grailsApplication.config.setting
}
void sendHistoricalContract(HistoricalContract hc_instance) {
//... blah blah whatever code
}
}
My guess is that GrailsApplication1 is causing a problem with the service that's keeping it from being injected into the controller, but I would think that it'd blow up with an exception at startup. Try running grails clean to force a full recompile.
I've run into this before.
I change it to grailsApplication1 and it worked.
Then you call:
this.setting = grailsApplication1.config.setting
Notice the case of the service
Burt's answer is helpful (+1 to Burt) but in case others are following the tutorial here:
http://www.grails.org/Services
and experiencing the same issue i had, i want to make it explicit:
Services go in their own files under
the Services directory, you do not
combine them with controllers, even
though it looks that way in the code
examples
See Burt's comment above on additional resources to Services and the Spring Framework.