If I have an interface
public interface TestService {
public String getSomething();
}
and a class
import org.apache.ignite.services.Service;
import org.apache.ignite.services.ServiceContext;
public class TestServiceImpl implements Service, TestService {
#Override
public void init(ServiceContext ctx) throws Exception {
}
#Override
public void execute(ServiceContext ctx) throws Exception {
}
#Override
public void cancel(ServiceContext ctx) {
}
#Override
public String getSomething() {
return "HelloWorld";
}
}
I deploy this service on ignite server nodes with
// Deploy services only on server nodes.
IgniteServices serverSvcs = ignite.services(ignite.cluster().forServers());
// Deploy cluster singleton.
serverSvcs.deployClusterSingleton("TestService", new TestServiceImpl());
And Ignite client node try to get the service
TestService testSvc = mIgnite.services().serviceProxy("TestService", TestService.class, false);
If the client node doesn't contain the "TestServiceImpl" class,
will catch exception with message:
"Failed to find class with given class loader for unmarshalling (make sure same versions of all classes are available on all nodes or enable peer-class-loading)",
Is it necessary that ignite client node must have the class TestServiceImpl ?
This was fixed already and the fix will be released in upcoming Ignite 1.6. In the meantime you can download the nightly build and check if it works for you: http://ignite.apache.org/community/contribute.html#nightly-builds
Related
So I have a web app with a specific route: http://localhost:28389/MyProjectName/webresources/test/ this returns just a json string:
But when I deploy my app on heroku the web app can't find the same path:
This is my ApplicationConfig:
#javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
addRestResourceClasses(resources);
return resources;
}
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(pkgServices.TestService.class);
}
}
And this is my TestService class:
#Path("test")
public class TestService {
public TestService () {
}
#GET
#Produces({MediaType.APPLICATION_JSON})
public Response getTestMsg() throws Exception {
return Response.ok("welcome").build();
}
}
Read Heroku docs. They allocate port number for you and set it to environment variable. You have to use this environment variable in your application to bind http server to this port.
Note, you will still connect to your app at 80th port from browser.
Current problem is Heroku cannot forward request to your server because you do not listen on port which Heroku expects you to listen to.
Since we found out that it is not possible to put the SecurityIdentity into an ContextualProxy as described here we try to find some kind of workaround.
We make a programmatic login on the the security subsystem of wildfly and run a Runnable with the returning Subject. The runnable should then be able to run certain EJBs depending on the Roles of the Subject, but the EJBContext or SessionContext is always "anonymous".
Code:
The login
public class RunnableHandlerImpl implements RunnableHandler {
#Override
public void runAsPrivileged(final ContextRunnable runnable) throws LoginException {
LoginContext ctx;
ctx = new LoginContext("myDomain", new MyCallbackHandler(runnable.getAuthToken()));
ctx.login();
Subject subject = ctx.getSubject();
Subject.doAs(subject, new PrivilegedExceptionAction() {
#Override
public Object run() throws Exception {
runnable.run();
return null;
}
});
}
call from mdb:
#Inject
MySingleton bean;
public void onMessage(Message msg) {
ContextRunnable contextRunnable = (ContextRunnable) message.getObject();
contextRunnable.setSingletonBean(bean);
RunnableHandler handler = new RunnableHandlerImpl();
handler.runAsPrivileged(contextRunnable);
}
The Runnable:
public class ContextRunnable implements Serializable, Runnable {
private MySingleton bean;
public void run() {
bean.printText("hello");
}
public void setSingletonBean(MySingleton bean) {
this.bean = bean;
}
}
The Singleton:
#Singleton
#SecurityDomain("DemoApplicationDomain")
#PermitAll
public class MySingleton {
#Resource EJBContext context;
#Resource SessionContext sessionCtx;
public void printText(String text) throws EJBAccessException {
System.out.println("ejbcontext: " + context.getCallerPrincipal().getName());
System.out.println("SessionContext: " + sessionCtx.getCallerPrincipal().getName());
System.out.println("text: " + text);
}
}
the login works just fine and I always get the right name from the principal but the ejbcontext and the sessioncontext are always 'anonymous'.
My guess is that the legacy security system of wildfly is not 'connected' with the ejb-container anymore since Elytron will be used.
Is there a way to fix this?
Also I tried to use the Elytron system as described here but with the same result:
AuthenticationConfiguration config = AuthenticationConfiguration.empty().useName("admin").usePassword("admin");
AuthenticationContext.empty().with(MatchRule.ALL, config)
.run(contextRunnable);
please ask if you need more code or information
I'm using Kinesis Client Library (KCL) and Spring boot. To use KCL, I have to implement a class (I named it RecordProcessor) for interface IRecordProcessor. And KCL will call this class and process records from kinesis. But when I tried to use dependency injection, I found it was not succeeded.
Here's the snippet for RecordProcessor:
#Component
public class RecordProcessor implements IRecordProcessor {
#Autowired
private SingleRecordProcessor singleRecordProcessor;
#Override
public void initialize(String shardId) {
...
}
#Override
public void processRecords(List<Record> records, IRecordProcessorCheckpointer checkpointer) {
...
}
}
I use Class SingleRecordProcessor to process single each record from kinesis. And this is my SingleRecordProcessor class snippet:
#Component
public class SingleRecordProcessor {
private Parser parser;
private Map<String, Table> tables;
public SingleRecordProcessor() {
}
#Autowired
private void setParser(Parser parser) {
this.parser = parser;
}
#Autowired
private void setTables(Map<String, Table> tables) {
this.tables = tables;
}
public void process(String record) {
...
}
}
I want to let spring framework automatically inject the SingleRecordProcessor instance into the class and use it. But I found that the field singleRecordProcessor is null.
Any idea why the dependency injection is failed? Or is it impossible to inject dependencies into a class which is called by other framework (in this case it's KCL)? Any suggestions will be appreciated! Really need some help please!!
[UPDATE]:
Sorry for not expressing the error clearly. The error was NullPointerException. I tried to inject singleRecordProcessor and call method process() on it. I think the injection was not successful so the instance singleRecordProcessor is null and there comes the NullPointerException.
More information is as follows:
I have a major class called Application
#SpringBootApplication
public class Application{
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application.class);
application.addListeners(new ApplicationPidFileWriter("./app.pid"));
ConfigurableApplicationContext ctx = application.run(args);
}
}
And I have the MainProcessor class which will call KCL.
#Service
public final class MainProcessor {
#EventListener(ApplicationReadyEvent.class)
public static void startConsumer() throws Exception {
init();
IRecordProcessorFactory recordProcessorFactory = new RecordProcessorFactory();
Worker worker = new Worker(recordProcessorFactory, kinesisClientLibConfiguration);
...
worker.run(); // this line will call KCL library and eventually call ProcessorRecord class.
}
}
[UPDATE2]
RecordProcessorFactory only has one method like this
#Component
public class RecordProcessorFactory implements IRecordProcessorFactory {
#Autowired
RecordProcessor recordProcessor;
#Override
public IRecordProcessor createProcessor() {
return recordProcessor;
}
}
It creates a new RecordProcessor instance for KCL to use it.
You should autowire an instance of this into your MainProcessor:
#Component
public class RecordProcessorFactory {
#Lookup IRecordProcessor createProcessor() { return null; }
}
Spring will instantiate a RecordProcessorFactory for you, and replace the implementation of createProcessor() in it with one that will return a new IRecordProcessor each time it's called. Both the factory and the processors will be Spring beans - which is what you want.
I'm trying to manage all my exceptions with an ExceptionMapper, as i saw in multiple documentation and examples. However, it doesn't seem to work, at least in my conditions.
I'm in a OSGI environment, using the Felix Witheboard pattern, with Amdatu Wink, so i don't have a web.xml and everything is supposed to be managed by itself.
I tried to register my ExceptionMapper as a service as i did with my web services, with no results.
#Component(immediate=true, provide={Object.class})
#Provider
public class SessionTimeoutExeptionHandler implements ExceptionMapper<SessionTimeoutException>{
public Response toResponse(SessionTimeoutException arg0) {
Response toReturn = Response.status(Status.FORBIDDEN)
.entity("session_timeout")
.build();
return toReturn;
};
}
Don't pay attention to the Response itself, i was just playing around.
My code is never called, how am i supposed to setup that provider?
You have to register the Provider in a javax.ws.rs.core.Application. That Application should be registered as a service with a higher service ranking than the default one created by the Amdatu Wink bundle.
The following is a working example.
The Exception Mapper itself:
#Provider
public class SecurityExceptionMapper implements ExceptionMapper<SecurityException>{
#Override
public Response toResponse(SecurityException arg0) {
return Response.status(403).build();
}
}
The Application:
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
public class MyApplication extends Application {
#Override
public Set<Object> getSingletons() {
Set<Object> s = new HashSet<Object>();
s.add(new JacksonJsonProvider());
s.add(new SecurityExceptionMapper());
return s;
}
}
Activator setting the service ranking property.
public class Activator extends DependencyActivatorBase{
#Override
public void destroy(BundleContext arg0, DependencyManager arg1) throws Exception {
}
#Override
public void init(BundleContext arg0, DependencyManager dm) throws Exception {
Properties props = new Properties();
props.put(Constants.SERVICE_RANKING, 100);
dm.add(createComponent().setInterface(Application.class.getName(), props).setImplementation(MyApplication.class));
}
}
Does anyone knows how to add a test Resource (i.e. one that is only for testing purposes and not added in run() method of the app)?
Here is an example:
public class MyTest {
#ClassRule
public static final DropwizardAppRule<TestConfiguration> RULE =
new DropwizardAppRule<TestConfiguration>(MyApp.class, "my-app-config.yaml");
#BeforeClass
public static void setUpBeforeClass() throws Exception
{
MyTest.RULE.getEnvironment().jersey().register(new JustForTestingResource());
}
#Test
public final void testTestResource()
{
Client client = new Client();
ClientResponse response = client.resource(
String.format("http://localhost:%d/rest/v1/test", RULE.getLocalPort()))
.get(ClientResponse.class);
assertThat(response.getStatus(), is(200));
}
}
and
public class JustForTestingRessource {
#GET
#Path("test")
#Produces(MediaType.APPLICATION_JSON)
public Response getInTestResource()
{
return Response.status(Status.OK).type(MediaType.TEXT_PLAIN).entity("get #Path(\"test\") is ok").build();
}
}
My problem is that the added resource is not added and I get resource not found 404 error response. It seems that I am registering the new resource after resource publishing and there is no refresh inside Dropwizard after start.
I dont want to extend my Application class and I dont want to insert test code into my real application code. Does anyone knows how to register the test resource without registering it in run() method of the Application?
This works, but a new class is needed:
public class TestService extends MyService{
#Override
public void run(
TestConfigurationconfiguration,
Environment environment) throws ClassNotFoundException
{
environment.jersey().register(new JustForTestingRessource());
super.run(configuration,environment);
}
}
Call in JUnit as already known:
#ClassRule
public static DropwizardAppRule<TestConfiguration> RULE =
new DropwizardAppRule<TestConfiguration>(TestService.class, "my-app-config.yaml");
Edit: Removing previous answer because it didn't solve your problem the way you wanted to do it.
I dug into the environment startup code and realized the reason why registering a controller didn't make it available is because jetty had already been started. If you stop jetty, register your controller and start jetty back up again, your resource will be available and you can use it in your test.
#BeforeClass
public static void setUpBeforeClass() throws Exception
{
MyTest.RULE.environment.applicationContext.stop()
MyTest.RULE.environment.jersey().register(new JustForTestingResource())
MyTest.RULE.environment.applicationContext.start()
}
You can test the Resource itself in a Jersey Container without starting a full dw-instance.
Check the "Testing Resources" section.
import static org.fest.assertions.api.Assertions.assertThat;
import static org.mockito.Mockito.*;
public class PersonResourceTest {
private static final PeopleStore dao = mock(PeopleStore.class);
#ClassRule
public static final ResourceTestRule resources = ResourceTestRule.builder()
.addResource(new PersonResource(dao))
.build();
private final Person person = new Person("blah", "blah#example.com");
#Before
public void setup() {
when(dao.fetchPerson(eq("blah"))).thenReturn(person);
// we have to reset the mock after each test because of the
// #ClassRule, or use a #Rule as mentioned below.
reset(dao);
}
#Test
public void testGetPerson() {
assertThat(resources.client().resource("/person/blah").get(Person.class))
.isEqualTo(person);
verify(dao).fetchPerson("blah");
}
}
I had the similar issue with the #ClassRule, maybe it can help to somebody..
In my test (Groovy) the invocation of RULE.getApplication() or getEnvironment() from #BeforeClass method returned null:
def setupSpec() {
RULE.application.run()
}
shown
java.lang.NullPointerException: Cannot invoke method run() on null object
I.e. RULE.testSupport had both null application and environment.
I found out that the call to
RULE.testSupport.before()
just before run() solves the error:
def setupSpec() {
RULE.testSupport.before()
RULE.application.run()
}
And then #AfterClass method:
def cleanupSpec() {
RULE.testSupport.after()
}
Or just use #Rule instead of #ClassRule and call
def setup() {
RULE.application.run()
}
inside of #Before method instead of #BeforeClass.
Though It seems strange, maybe there is some other better solution exists..
public class TestMain extends Main{
public static void main(String ... args) throws Exception {
new TestMain().run(args);
}
#Override
public void initialize(Bootstrap<AppConfiguration> bootstrap) {
super.initialize(bootstrap);
bootstrap.addBundle(
new MigrationsBundle<AppConfiguration>() {
#Override
public DataSourceFactory getDataSourceFactory(
AppConfiguration configuration) {
return configuration.getDataSourceFactory();
}
});
}
}