New to Eclipse RCP (e4), am trying to get a handler to update a UI widget within a Part.
I have tried injecting the EPartService to first access the Part by ID, like so:
public class Example {
public static final String PART_ID = “au.org.example.app.part”;
#Inject
private EPartService partService;
public void eventOccured()
{
MPart part = partService.findPart(PART_ID); // exception thrown here
}
}
But this is throwing a NPE.
findPart() should at least safely return null if the ID were incorrect? So what am I missing?
Am also open to suggestions of relevant tutorials (have worked through some of Lars Vogella's great tutorials, but to no avail for this problem).
Any further info required please let me know.
EDIT : Looks like EPartService is not being injected? Have I not added it correctly?
Injection is only done automatically on objects which are known to the Application Model - things like parts and handlers.
For objects which you create you can do injection using the ContextInjectionFactory. You can create an object with:
#Inject
IEclipseContext context;
...
MyClass myClass = ContextInjectionFactory.make(MyClass.class, context);
or you can do injection on an existing class instance with:
ContextInjectionFactory.inject(myClass, context);
in this case injection is not done on the class constructor.
There are other variants of make and inject which have a second context which allows additional values to be added to the context being injected.
Related
I have a question and it is related to the error that I am getting. How bad is it really to have a circular reference in my service? I know very well what the error is due to and how to possibly solve it, only that in the company where I work a Senior recommended me that for transactional issues it is necessary to make such a circular reference and in fact it is a very recurrent practice there, but as I am starting a personal project from scratch is the first time I get the error and it triggered the doubt again. Thank you very much in advance!
Here is the code of the service
public class MedicalRecordServiceImpl implements MedicalRecordService {
private final MedicalRecordRepository medicalRecordRepository;
private final MedicalRecordService medicalRecordService;
private final PatientService patientService;
private final TutorService tutorService;
private final MedicalHistoryAnswerService medicalHistoryAnswerService;
private final DentalHistoryAnswerService dentalHistoryAnswerService;
public MedicalRecordServiceImpl(MedicalRecordRepository medicalRecordRepository, MedicalRecordService medicalRecordService, PatientService patientService, TutorService tutorService, MedicalHistoryAnswerService medicalHistoryAnswerService, DentalHistoryAnswerService dentalHistoryAnswerService) {
this.medicalRecordRepository = medicalRecordRepository;
this.medicalRecordService = medicalRecordService;
this.patientService = patientService;
this.tutorService = tutorService;
this.medicalHistoryAnswerService = medicalHistoryAnswerService;
this.dentalHistoryAnswerService = dentalHistoryAnswerService;
}
#Override
#Transactional(propagation = Propagation.REQUIRED)
public void saveMedicalRecord(MedicalRecordEntity medicalRecord) {
medicalRecordRepository.save(medicalRecord);
}
#Override
#Transactional(propagation = Propagation.REQUIRED)
public ResponseEntity<?> createNewMedicalRecord(MedicalRecordDTO medicalRecordDTO) {
PatientEntity patient = this.storeMedicalRecordIntoPatient(medicalRecordDTO);
TutorEntity tutor = this.storeMedicalRecordIntoTutor(medicalRecordDTO);
List<MedicalHistoryAnswerEntity> medicalHistoryAnswers = this.storeMedicalRecordIntoMedicalHisAns(medicalRecordDTO);
List<DentalHistoryAnswerEntity> dentalHistoryAnswers = this.storeMedicalRecordIntoDentalHisAns(medicalRecordDTO);
patientService.savePatient(patient);
tutor.setPatient(patient);
tutorService.saveTutor(tutor);
MedicalRecordEntity medicalRecord = this.createMedicalRecord(patient, tutor);
medicalRecordService.saveMedicalRecord(medicalRecord);
medicalHistoryAnswers.forEach(medicalHistoryAnswer -> {
medicalHistoryAnswer.setMedicalRecord(medicalRecord);
medicalHistoryAnswerService.saveMedicalHistoryAnswer(medicalHistoryAnswer);
});
dentalHistoryAnswers.forEach(dentalHistoryAnswer -> {
dentalHistoryAnswer.setMedicalRecord(medicalRecord);
dentalHistoryAnswerService.saveDentalHistoryAnswer(dentalHistoryAnswer);
});
return ResponseEntity.status(HttpStatus.OK).body("");
}
}
The only reason why you may need circular dependency is the case when you want to access to "this" as to a bean to trigger annotated method logic.
For example if you have two methods "foo" (annotated with #Transactional) and "bar" (invokes "foo" within). You will have to use self injection to trigger transaction in case of invocation bar>foo (selfBean.foo() instead of this.foo()).
Also you can use #Lasy for self injection to avoid the circular dependency error.
But it's a pretty ugly solution and you should avoid it if it's possible. It depends on the situation, may be it's possible to split logic to different services or use TransactionTemplate.
As you said, I will assume that you know what the error is and how to resolve it. A circular reference is bad for the following reason:
Spring loads beans the moment you start the project, meaning it loads each bean in the correct order so it can load all beans and references them successfully. If you have a circular reference Spring won't know with which bean to start first, and so the error occurs. It's about how Spring works.
I also had this error in my current project and you are not limited to not making the circular reference, you just need to instruct Spring, so that it knows how to handle each bean in these cases.
Well, imagine this:
You get a new phone, you are all excited about it. You want to unlock it, but it protectd with password. The password is available inside the notes in the locked phone.
So, you want to use your phone, for it you need the pass. You want the pass, for it you need to unlock the phone. You want to use your phone, for it you need your pass... Etc.
The same happens when you have circular references, for A you need B, for B you need A, so you cannot create A and cannot create B either and cannot proceed.
I am working on refactoring our code according to Sonar and Kiuwan analyzers recommendations. Our architecture is standard MVC Java Web App based on Struts 2.x framework deployed on Apache Tomcat 9.x. App itself is basically an information system that allows users to browse pdf documents and perform actions on them.
I have run into a design flaw which I am not sure how to solve or if it even is an problem all togther.
During http request processing we set set up Hibernate's Entity Manager instance in Interceptor class before Struts Actions are called. We are using this EM instance for the whole lifecycle of the Struts action. When the action finishes the interceptor closes the EM instance. The EM instance is saved into instance of action class as an class attribute. Snippet below.
class BaseAction extends ActionSupport implements EntityManagerAware { //EntityManagerAware my interface that allows interceptor to inject em instance into underlying Action class
private EntityManager em;
private String someParam;
#Action(value = "welcome", results = {#Result(name = SUCCESS, type = "tiles", location = "welcome")})
public String input() {
em.doStuffWithEntities();
log.trace("Some param": + someParam);
return SUCCESS;
}
...
}
I have always thought this is solution is OK, but now we introduced Sonar. Sonar marks em attribute as - Make "em" transient or serializable. I understand that Sonar thinks it is an attribute that might be passed during HttpRequests, line someParam attribute in the snippet above.
My question is do Struts action attributes need to be Serializable (even the ones like "em") ? Can I somehow solve this with perhaps Struts annotation or simply with transient flag? When does serialization of Action class instance occur ? Can it occur ?
Basically can somebody explain this in greater detail (I can always just mark this Sonar issue as false positive, but I really do not know how this works) ? I have googled and googled but came up empty handed.
Thank you very much,
Jiri
EntityManager should be a persistent dependency, for example:
#PersistenceUnit(unitName = "QueryPersistenceUnit")
private EntityManagerFactory entityManagerFactory;
public EntityManager getEntityManager() {
return entityManagerFactory.createEntityManager();
}
I have a Wicket application and I'm trying to implement separate configuration that can be changed remotely. That's the end goal, anyway.
What I'm trying to do is set up Cayenne to work by starting it manually, rather than using the web.xml file. I have tried a bunch of different things, but I'm not sure I fully understand how the context is applied to all threads.
I have tried creating a ServerRuntime in my Application class. I've also tried on my custom BasePage class that each page uses. I can get it to kind of work by doing the following on the BasePage, but it is inconsistent:
public class BasePage ....
public static ServerRuntime runtime = new ServerRuntime("cayenne-config.xml");//This is in my BasePage class, but I've also tried this in the Application class
#Override
protected void init() {
BaseContext.bindThreadObjectContext(Application.runtime.getContext());//This is in my BasePage class
}
Like I said, that kind of works, but it isn't consistent. I keep getting errors on
BaseContext.getThreadObjectContext();
Error is this:
java.lang.IllegalStateException: Current thread has no bound ObjectContext.
I can't seem to find much information on this. I tried doing stuff like this, and accessing the runtime using these as well, but nothing is working consistently.
WebUtil.setCayenneRuntime(this.getServletContext(), runtime);
BaseContext.bindThreadObjectContext(WebUtil.getCayenneRuntime(((Application)getApplication()).getServletContext()).getContext());
Any help would be greatly appreciated.
I figured out a way to do this on my own.
I'm extending CayenneFilter and overriding the init method.
In there I copied nearly their exact code. I will be able to check for any config here and load the proper xml file. This obviously isn't the ironed out solution, but is definitely a step forward, and could be the way I end up doing this.
Either way, here's what I have tested to be working.
#WebFilter(filterName = "cayenne-config", displayName = "cayenne-config", urlPatterns = {"/*"})
public class TestFilter extends CayenneFilter
{
#Override
public void init(FilterConfig config) throws ServletException
{
this.checkAlreadyConfigured(config.getServletContext());
this.servletContext = config.getServletContext();
WebConfiguration configAdapter = new WebConfiguration(config);
Collection modules = configAdapter.createModules(new Module[]{new WebModule()});
ServerRuntime runtime = new ServerRuntime("cayenne-test.xml", (Module[])modules.toArray(new Module[modules.size()]));
WebUtil.setCayenneRuntime(config.getServletContext(), runtime);
}
}
I don't think the annotation is needed (I am specifying it all in the web.xml file), but I thought I would leave it here so you could see that it is changing.
If I could find a way to change the config (FilterConfig) values (the init parameters), then I could just change that to the name of the xml file I want to use and not override this entire method. I couldn't figure out how to do that, but I'll look further later.
If anyone has another better answer, I would love to hear it.
I'm trying to use AOP with picocontainer.
so far I found in the documentation:
http://picocontainer.codehaus.org/interception.html
pico = new DefaultPicoContainer();
pico.as(INTERCEPT).addComponent(Apple.class, BraeburnApple.class);
and then create the interceptor, but looking through the code, I cannot find the INTERCEPT property anywhere.
as receives a Properties value, which pico implements in Characteristics class.
anyone has a clue, or has implemented it before and knows how to keep with it?
Thanks
looks like the property for this Behavior is somehow missing in this pico version, check org.picocontainer.Characteristics in older versions, I really hope it was implemented somewhere :)
Also there's old styled way for interception in pico: http://www.markhneedham.com/blog/2008/11/11/logging-with-pico-container/
Since the 2.14.3 org.picocontainer.behaviors still have these classes, I suppose this way is ok
This worked for me. First, create a proxy by extending a bean:
public static class ChangeMapInfoEndpointInterceptor extends MapInfoRoutingManagementBean {
#Override
public void setEndpoint(String endpoint) {
System.out.println("setEndpoint called");
}
}
Then pass it to the intercepting-styled container:
MutablePicoContainer context = new PicoBuilder().withBehaviors(new Intercepting()).build();
context.addComponent(MapInfoRoutingManagement.class, MapInfoRoutingManagementBean.class);
Intercepted intercepted = context.getComponentAdapter(MapInfoRoutingManagement.class).findAdapterOfType(Intercepted.class);
intercepted.addPostInvocation(MapInfoRoutingManagement.class, new ChangeMapInfoEndpointInterceptor());
I am facing a problem in converting my state pattern using plain java to spring DI since I am new to spring.
Actually I made a project using state pattern but I took the approach that every state knows it successive states not the context class.
The context class has a field "currentState" its type is IState, and it has method setState(IState state).
The IState has one method geNext(Context context).
And in the context class I made a while(keepOn) keepOn is true and it become false in ExitState to stop processing, in this loop I call currentState.goNext().
Each state make some database transactions and webservice's calls and depending on the result it set the next state using context.setState(new StateFour()) -for example-.
The first state is set by the client after creating the context.
Code sample:
public interface IState{public void goNext(Context context);}
public class StateOne implements IState{
public void goNext(Context context){
//do some logic
if(user.getTitle.equals("manager"){context.setState(new StateThree());}
else if(user.getTitle.equals("teamLead"){context.setState(new StateTwo());}
else{context.setState(new ExitState());}
}
}
public class Context{
private boolean keepOn = true;
private IState currentState;
public void setState(IState state){
currentState = state;
}
while(keepOn){currentState.goNext(this);}
}
Now I am trying to use spring DI annotation-based, the problem I am facing is that the context will annotated "currentState field" with #Autowired but I need the spring container to do the same logic if I am in state one and "if statement" success inject state three "else if" inject state two otherwise inject exitState.
If I use #Qualifier(value ="stateOne") it will specify only the first state which implements the interface but the other states which I set depending on the situation I don't know how to specify it in spring.
Also org.springframework.core.Ordered need specifying the orders of the beans in advance but I don't know the values I will receive from the database or webservice in advance, it should be specified at runtime.
So is it possible to replace this plain java with spring DI and how?
Thanks in advance for any help and sorry for lengthening.
You should use ApplicationContext. Example below:
// Inject application context into your bean
#Autowired
ApplicationContext applicationContext;
// Get bean from the context (equivalent to #Autowired)
applicationContext.getBean(StateThree.class);
The most versatile way to auto wire the state is by registering a resolvable dependency with a ConfigurableListableBeanFactory. As a dependency you could drop in your implementation of org.springframework.beans.factory.ObjectFactory<T> which will get the current user and creates/fetches the state to be injected.
This is exactly what happens when you, for instance, auto wire a field of type HttpServletRequest. A RequestObjectFactory will get the current request and inject it using this implementation.
// org.springframework.web.context.support.WebApplicationContextUtils
private static class RequestObjectFactory implements ObjectFactory<ServletRequest>, Serializable {
#Override
public ServletRequest getObject() {
return currentRequestAttributes().getRequest();
}
#Override
public String toString() {
return "Current HttpServletRequest";
}
}