Since it's initialized in declaration, and the import implies by itself a dependency.
We have a jUnit parent test class like...
public class ServerTestBase extends TestBase {
public static final Client client = new Client();
...
And a Suite with the static import of the client and some init code in a #ClassRule using this client:
import static jwstest.test.ServerTestBase.client;
#RunWith(Suite.class)
#Suite.SuiteClasses({BunchOfSuites.class})
public class ScratchSuite {
#ClassRule
public static final ExternalResource testRule = new ExternalResource() {
#Override
protected void before() throws Throwable {
response = client.call(someService, HttpVerbs.GET).getResponse();
So, again, I don't understand, how in hell client can be null, since it's initialized on declaration, and the static import implies a dependency.
¿Any ideas? Thank you in advance.
The docs say that the field accessible in the #ClassRule has to be public static.
Static import is not such thing.
You can either extend ServerTestBase:
public class ScratchSuite extends ServerTestBase { ... }
... OR declare public static anew:
public static Client myClient = client; //from static import
Related
I’m toying with an basic infinispan cluster and I came across a puzzling error.
I’m basically implementing a shared map, holding just one Integer
Here is the code of my service
package sandbox.infinispan.test.service;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.infinispan.Cache;
#Named("useThisOne")
#ApplicationScoped
public class CounterService implements ICounterService {
private static final String KEY = "key";
#Inject
private Cache<String, Integer> cache;
#Override
public void inc(final int amount) {
this.cache.put(KEY, Integer.valueOf(this.get() + amount));
}
#Override
public int get() {
return this.cache.computeIfAbsent(KEY, k -> Integer.valueOf(0)).intValue();
}
}
Cache is produced with the following:
package sandbox.infinispan.test.config;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfiguration;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;
#Dependent
class CacheProvider {
#Produces
#ApplicationScoped
private EmbeddedCacheManager defaultClusteredCacheManager() {
final GlobalConfiguration g = new GlobalConfigurationBuilder() //
.clusteredDefault() //
.transport() //
.nodeName(this.getNodeName()) //
.clusterName("infinispanTestCluster") //
.build();
final Configuration cfg = new ConfigurationBuilder() //
.clustering() //
.cacheMode(CacheMode.REPL_SYNC) ///
.build();
return new DefaultCacheManager(g, cfg);
}
}
When there are at least two servers in the cluster, computeIfAbsent fails with
15:48:50,253 ERROR [org.infinispan.interceptors.impl.InvocationContextInterceptor] (jgroups-7,myhostname-14393) ISPN000136: Error executing command ComputeIfAbsentCommand, writing keys [key]: org.infinispan.remoting.RemoteException: ISPN000217: Received exception from otherhostname-44445, see cause for remote stack trace
which drills down to:
Caused by: java.lang.NoSuchMethodException: sandbox.infinispan.test.service.CounterService.$deserializeLambda$(java.lang.invoke.SerializedLambda)
and finally to:
Caused by: java.lang.IllegalArgumentException: Invalid lambda deserialization
at sandbox.infinispan.test.service.CounterService.$deserializeLambda$(CounterService.java:10)
... 68 more
Caused by: an exception which occurred:
in object of type java.lang.invoke.SerializedLambda
If I rewrite my pretty nice fashionable code to the ugly following, it works.
#Override
public int get() {
Integer value = this.cache.get(KEY);
if (value == null) {
value = Integer.valueOf(0);
this.cache.put(KEY, value);
}
return value.intValue();
}
How can I use the pretty computeIfAbsent way of doing things nowadays ?
Eclipse 2018-12, WildFly 14, java 10 on of the dev member of the cluster, CentOs 7, OpenJdk 10, WildFly 14 on the remote cluster member.
Thanks for your help
Solved (kinda)
Thanks to the help I received here, I transformed the lambda into an inner class :
static class OhWell implements Serializable {
static Integer zero(final String t) {
return Integer.valueOf(0);
}
}
#Override
public int get() {
return this.cache.computeIfAbsent(KEY, OhWell::zero).intValue();
}
It works now, but it’s lots less nice than the neat lambda. So I’ll stick to the old-fashioned way – unless someone can think of a better way to do it.
Further results:
The following static inner class with a static method works
static class StaticOhWell implements Serializable {
static Integer apply(final String t) {
return Integer.valueOf(0);
}
}
#Override
public int get() {
return this.cache.computeIfAbsent(KEY, StaticOhWell::apply).intValue();
}
The following non static inner class with a non static method fails :
class NotStaticOhWell implements SerializableFunction<String, Integer> {
#Override
public Integer apply(final String t) {
return Integer.valueOf(0);
}
}
#Override
public int get() {
return this.cache.computeIfAbsent(KEY, new NotStaticOhWell()::apply).intValue();
}
It fails with this error message NotSerializableException: org.infinispan.cache.impl.EncoderCache:
13:41:29,221 ERROR [org.infinispan.interceptors.impl.InvocationContextInterceptor] (default task-1) ISPN000136: Error executing command ComputeIfAbsentCommand, writing keys [value]: org.infinispan.commons.marshall.NotSerializableException: org.infinispan.cache.impl.EncoderCache
Caused by: an exception which occurred:
in field sandbox.infinispan.test.service.CounterService.cache
in object sandbox.infinispan.test.service.CounterService#4612a6c3
in field sandbox.infinispan.test.service.CounterService$NotStaticOhWell.this$0
in object sandbox.infinispan.test.service.CounterService$NotStaticOhWell#4effd362
in field java.lang.invoke.SerializedLambda.capturedArgs
in object java.lang.invoke.SerializedLambda#e62f08a
in object sandbox.infinispan.test.service.CounterService$$Lambda$1195/1060417313#174a143b
Final words (?)
Using a “static lambda” (a static inner class implementing the SerializableFunction interface) worked too
static class StaticSerializableFunction implements SerializableFunction<String, Integer> {
#Override
public Integer apply(final String t) {
return Integer.valueOf(0);
}
}
#Override
public int get() {
return this.cache.computeIfAbsent(KEY, new StaticSerializableFunction()::apply).intValue();
}
And the winner is…
Making the class actually serializable by “transienting” the Cache allows to simply use a method of this class. No need to create an inner class!
package sandbox.infinispan.test.service;
import java.io.Serializable;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.infinispan.Cache;
#Named("useThisOne")
#ApplicationScoped
public class CounterService implements ICounterService, Serializable {
private static final String KEY = "value";
#SuppressWarnings("cdi-ambiguous-dependency")
#Inject
private transient Cache<String, Integer> cache;
#Override
public void inc(final int amount) {
this.cache.put(KEY, Integer.valueOf(this.get() + amount));
}
#Override
public int get() {
return this.cache.computeIfAbsent(KEY, this::zero).intValue();
}
private Integer zero(#SuppressWarnings("unused") final String unused) {
return Integer.valueOf(0);
}
#Override
public void reset() {
this.cache.clear();
}
}
Thanks all!
According to Unable to deserialize lambda the deserializer needs the actual code to be available. Are you sure that your application is already started on all other nodes in the cluster (the exact same version, including your lambda)?
The computeIfAbsent() sends the lambda directly to the data (and therefore handles the operation using one RPC, instead of first fetching the value and then writing it as the 'ugly code'). In WF, your application lives in a different classloader (module) than Infinispan and that might cause an issue.
Could you try to refactor your lambda into a class and see if you get similar problem? I am not that knowledgeable about WF, so there might be a mitigation for regular classes that is missing for lambdas.
I need to run inner class test cases from eclipse using Junit4. I understand that there is org.junit.runners.Enclosed that is intended to serve this purpose. It works well for "plain" unit test i.e. without the need for spring context configuration.
For my case, give sample code below, Adding another annotation of Enclosed does not work since there is a conflict of both SpringJUnit4ClassRunner and Enclosed test runners. How can I solve this problem ?
Note: Kindly ignore any basic spelling mistake/basic import issues in the below example since I tried to cook up from my actual use-case.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "/unit-test-context.xml"})
public class FooUnitTest {
// Mocked dependency through spring context
#Inject
protected DependentService dependentService;
public static class FooBasicScenarios extends FooUnitTest{
#Test
public void testCase1 {
.....
List<Data> data = dependentService.getData();
.....
}
}
public static class FooNeagativeScenarios extends FooUnitTest{
#Test
public void testCase1 {
.....
List<Data> data = dependentService.getData();
.....
}
}
}
}
FooUnitTest is a container, you cannot use it as a superclass.
You need to move all your spring-code to Scenario-classes. And use #RunWith(Enclosed.class). For example, with abstract superclass
#RunWith(Enclosed.class)
public class FooUnitTest {
#ContextConfiguration(locations = { "/unit-test-context.xml"})
protected abstract static class BasicTestSuit {
// Mocked dependency through spring context
#Inject
protected DependentService dependentService;
}
#RunWith(SpringJUnit4ClassRunner.class)
public static class FooBasicScenarios extends BasicTestSuit {
#Test
public void testCase1 {
.....
List<Data> data = dependentService.getData();
.....
}
}
#RunWith(SpringJUnit4ClassRunner.class)
public static class FooNeagativeScenarios extends BasicTestSuit {
#Test
public void testCase1 {
.....
List<Data> data = dependentService.getData();
.....
}
}
}
Of course you can declare all dependencies in each Scenario-class, in that case there is no necessary in abstract superclass.
//main.fla
var skill1 = addChild(girl2.skill1);
i want to access the skill1 var in girl2.as, but it didn't work.
The error was shown :
1119: Access of possibly undefined property skill1 through a reference with static type Icons.chars:girl2.
//girl2.as
package Icons.chars
{
import flash.display.Loader;
import flash.display.MovieClip;
import flash.net.URLRequest;
public class girl2 extends charsel {
public static var skill1:Loader, url1:URLRequest;
public function girl2 () {
skill1 = new Loader();
url1 = new URLRequest("skills/nami/skill4.png")
skill1.load(url1);
I tried in charsel.as and it worked
//charsel.as
package Icons.chars
{
import flash.geom.Point;
import flash.display.*;
import flash.events.MouseEvent;
public class charsel extends MovieClip {
protected var originalPosition:Point;
public static var player1:MovieClip, player2:MovieClip, player3:MovieClip;
I tried to access player1 and it worked.
I am not sure why you would want to use a static modifier in this case. Note, that even though you have declared skill1 as a static it will actually become available only when you create an instance of the girl2 class - as you creating it in the constructor (also note, that you should name your classes with a capital letter, so this should be Girl2).
So, I would either remove all static modifiers for public variables or, if there are any specific reasons for that, use a static initialiser to instantiate skill1 variable:
public class girl2 extends charsel {
public static var skill1:Loader, url1:URLRequest;
{
skill1 = new Loader();
skill1.addEventListener(...); // event handlers should be static as well
skill1.load(...);
}
public function girl2 () {
Use Case
I am trying to use Adding custom behaviour to all repositories functionality of Spring Data MongoDB.
The documentation unhelpfully describes how to connect using JPA. Anyways got the config setup with Mongo equivalent.
I want to add a findByCategoryName(String categoryName) method to all entities as all my entities will have a Category . Category is a DBRef object so have to use custom query.
Below is relevant part of the config
<!-- Activate Spring Data MongoDB repository support -->
<mongo:repositories base-package="com.domain.*.repo" repository-impl-postfix="CustomImpl"
factory-class="com.domain.commonrepo.CommonMongoRepoFactoryBean"/>
<bean id="mappingContext" class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" />
<mongo:mapping-converter mapping-context-ref="mappingContext">
<mongo:custom-converters base-package="com.domain.mongo.converter" />
</mongo:mapping-converter>
<bean id="entityInformationCreator" class="org.springframework.data.mongodb.repository.support.DefaultEntityInformationCreator">
<constructor-arg name="mappingContext" ref="mappingContext" />
</bean>
.
.
The FactoryBean
#NoRepositoryBean
public class CommonMongoRepoFactoryBean<T extends MongoRepository<?,?>, ID extends
Serializable> extends MongoRepositoryFactoryBean{
#Autowired
private static MongoTemplate mongoTemplate;
protected MongoRepositoryFactory getRepositoryFactory(Class<T> clazz) {
return new CommonMongoRepoFactory(clazz);
}
private static class CommonMongoRepoFactory extends MongoRepositoryFactory {
private Class clazz;
public CommonMongoRepoFactory(Class clazz) {
super(mongoTemplate);
this.clazz = clazz;
}
public CommonMongoRepoImpl getTargetRepository() {
return new CommonMongoRepoImpl(clazz);
}
public Class<?> getRepositoryClass() {
return CommonMongoRepoImpl.class;
}
}
I know it's a bit of a hack but with no documentation it is a pain. If anyone knows better PLEASE give me a github link :-)
Common Repo interface
#NoRepositoryBean
public interface CommonMongoRepo<T, ID extends Serializable> extends MongoRepository<T,ID> {
public List<T> findByCategoryName(String categoryName);
Implementation
#NoRepositoryBean
public class CommonMongoRepoImpl<T, ID extends Serializable> extends SimpleMongoRepository<T,
ID> implements CommonMongoRepo<T, ID> {
private Class<T> type;
#Autowired
private static MongoTemplate mongoOperations;
#Autowired
private static EntityInformationCreator entityInformationCreator;
#Autowired
private CategoryRepo categoryRepo;
public CommonMongoRepoImpl(Class<T> type) {
super((MongoEntityInformation<T, ID>) entityInformationCreator.getEntityInformation(type), mongoOperations);
}
#Override
public List<T> findByCategoryName(String categoryName) {
Category category = categoryRepo.findByName(categoryName);
return mongoOperations.find(query(where("categories.$id").is(category.getId())), type);
}
PROBLEM
Now when I am trying to use the common method I get an exception
No Property category found in "Entity". Which is I guess when mongo repo is trying to auto implement the method. This is inspite of me declaring the bean as #NoRepositoryBean
PLEASE HELP!!! Dont want to add the same custom method to all the entities
Here is the best solution!
Step One:
Add a custom method to interface!
增加一个自定义的方法
#custom interface
/**
* Basic Repository for common custom methods
* #author liangping
*/
import java.io.Serializable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
#NoRepositoryBean
public interface WootideRepositoryCustom <T, ID extends Serializable>
extends PagingAndSortingRepository<T, ID>, MongoRepository<T, ID> {
public Page<T> search(Query query, Pageable pageable);
}
Implementation
Step Two:
Add implement for your custom method!
实现你的自定义方法
/**
* implement for wootide basic repository
* #author liangping
*/
import java.io.Serializable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.mongodb.repository.support.SimpleMongoRepository;
public class WootideRepositoryImpl<T, ID extends Serializable> extends
SimpleMongoRepository<T, ID> implements WootideRepositoryCustom<T, ID> {
public WootideRepositoryImpl(MongoEntityInformation<T, ID> metadata,
MongoOperations mongoOperations) {
super(metadata, mongoOperations);
}
#Override
public Page<T> search(Query query, Pageable pageable) {
long total = this.getMongoOperations().count(query, this.getEntityInformation().getJavaType() );
return new PageImpl<T>(this.getMongoOperations().find(query.with(pageable), this.getEntityInformation().getJavaType()), pageable, total);
}
}
Create a new factory for custom repository
/**
* Repository Factory for all Subrepository
* #author liangping
*/
import java.io.Serializable;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation;
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory;
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
public class WootideRepositoryFactoryBean<R extends MongoRepository<T, I>, T, I extends Serializable>
extends MongoRepositoryFactoryBean<R, T, I> {
#Override
protected RepositoryFactorySupport getFactoryInstance(
MongoOperations operations) {
return new WootideMongoRepositoryFactory<T,I>( operations );
}
private static class WootideMongoRepositoryFactory<T, ID extends Serializable>
extends MongoRepositoryFactory {
private MongoOperations mongo;
public WootideMongoRepositoryFactory(MongoOperations mongoOperations) {
super(mongoOperations);
this.mongo = mongoOperations;
}
#SuppressWarnings("unchecked")
protected Object getTargetRepository(RepositoryMetadata metadata) {
TypeInformation<T> information = ClassTypeInformation.from((Class<T>)metadata.getDomainType());
MongoPersistentEntity<T> pe = new BasicMongoPersistentEntity<T>(information);
MongoEntityInformation<T,ID> mongometa = new MappingMongoEntityInformation<T, ID>(pe);
return new WootideRepositoryImpl<T, ID>( mongometa, mongo);
}
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return WootideRepositoryCustom.class;
}
}
}
Make it works
<mongo:repositories base-package="com.***.mongodb"
factory-class="com.***.mongodb.custom.WootideRepositoryFactoryBean"/>
Good Luck! 祝你好运!
Somewhat delayed but here is sample code that does this for a Spring web app project. The salient points are:
Interface used in Controller
Implementation done in a separate class that inherits from a base
The base implementation provides common methods that any other Controller can use with just a quick inheritance
I've been through a few documentations, but am not able to communicate to the datastore yet...can anyone give me a sample project/code of objectify used in GWT web app(I use eclipse)...just a simple 'put' and 'get' action using RPC should do...or, atleast tell me how its done
Easiest way to understand how to make objectify work is to repeat all steps described in this article from David's Chandler blog. Whole blog is a pretty much must read if you interested in GWT, GAE(Java), gwt-presenter, gin\guice,etc. There you will find working example, but anyway here i'll show a slighly advanced example.
In package shared define your entity/model:
import javax.persistence.Embedded;
import javax.persistence.Id;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Unindexed;
#Entity
public class MyEntry implements IsSerializable {
// Objectify auto-generates Long IDs just like JDO / JPA
#Id private Long id;
#Unindexed private String text = "";
#Embedded private Time start;
// empty constructor for serialization
public MyEntry () {
}
public MyEntry (Time start, String text) {
super();
this.text = tText;
this.start = start;
}
/*constructors,getters,setters...*/
}
Time class (also shared package) contains just one field msecs:
#Entity
public class Time implements IsSerializable, Comparable<Time> {
protected int msecs = -1;
//rest of code like in MyEntry
}
Copy class ObjectifyDao from link above to your server.dao package. And then make DAO class specifically for MyEntry -- MyEntryDAO:
package com.myapp.server.dao;
import java.util.logging.Logger;
import com.googlecode.objectify.ObjectifyService;
import com.myapp.shared.MyEntryDao;
public class MyEntryDao extends ObjectifyDao<MyEntry>
{
private static final Logger LOG = Logger.getLogger(MyEntryDao.class.getName());
static
{
ObjectifyService.register(MyEntry.class);
}
public MyEntryDao()
{
super(MyEntry.class);
}
}
Finally we can make requests to database(server package):
public class FinallyDownloadingEntriesServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws
ServletException, IOException {
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/plain");
//more code...
resp.setHeader("Content-Disposition", "attachment; filename=\""+"MyFileName"+".txt\";");
try {
MyEntryDao = new MyEntryDao();
/*query to get all MyEntries from datastore sorted by start Time*/
ArrayList<MyEntry> entries = (ArrayList<MyEntry>) dao.ofy().query(MyEntry.class).order("start.msecs").list();
PrintWriter out = resp.getWriter();
int i = 0;
for (MyEntry entry : entries) {
++i;
out.println(i);
out.println(entry.getStart() + entry.getText());
out.println();
}
} finally {
//catching exceptions
}
}