You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@velocity.apache.org by Alexandre Akoulov <sa...@bisinfo.com.au> on 2004/06/25 08:18:56 UTC

Can't reference methods from supertype that has package access

Hi all,

I'd greatly appreciate if you could shed some light on the following issue.

---------------------------------------------------------------------------
Problem description (on Velocity 1.4)
---------------------------------------------------------------------------

If a public interface (class) extends another interface (class) that has
package access Velocity only sees methods that
are declared in the public interface when a variable of public interface
type is used in Velocity template.

It seems that Velocity does not see methods that are declared in the public
interface's
parent, which has package access.

If supertype (parent of public interface) has public access Velocity sees
methods declared both in public interface
and its supertype.

The following example demonstrates this problem.

---------------------------------------------------------------------------
Package "employee" has the following interfaces and classes defined:
---------------------------------------------------------------------------

// Interface that is only visible to classes/interfaces defined in the same
// package (i.e. "employee" package)
interface EmployeeBase {
	// The only method
	public String getFullName();
}


// Interface that is visible to everyone. All methods declared in this
interface and its supertypes
// are visible to everyone
public interface Employee extends EmployeeBase {
	// Additional method to the ones declared in EmployeeBase
	public String getFirstName();
}


---------------------------------------------------------------------------
Package "renderers" has got the following class:
---------------------------------------------------------------------------

public class EmployeeRenderer {
      // Renders employee html using Velocity
      public void render(java.io.Writer writer) throws Exception {
	org.apache.velocity.VelocityContext context = getContext();
            org.apache.velocity.Template template = getTemplate();

             // Get new employee
            employee.Employee employee = getEmployee();
            // Place employee into the velocity context
            context.put("employee", employee);
            // Merge into the velocity template
            template.merge(context, writer);
     }
}

---------------------------------------------------------------------------
In the velocity template:
---------------------------------------------------------------------------

<tr>
	<th align='right'>Employee First Name:</th>
	## Executing a method that is declared in the interface with public access
(i.e. Employee interface)
	<td> $employee.getFirstName()</td>
</tr>

<tr>
	<th align='right'>Employee Full Name:</th>
	## Executing a method that is declared in the interface with package access
(i.e. EmployeeBase interface)
	<td>$employee.getFullName()</td>
</tr>

---------------------------------------------------------------------------
The Problem is that Velocity does not seem to recognise that  $employee
variable (i.e. employee.Employee interface) has getFullMethod as generated
html has the following:
---------------------------------------------------------------------------

<tr>
	<th align='right'>Employee First Name:</th>
	## Executing a method that is declared in the interface with public access
(i.e. Employee interface)
	<td>First Name</td>
</tr>

<tr>
	<th align='right'>Employee Full Name:</th>
	## Executing a method that is declared in the interface with package access
(i.e. EmployeeBase interface)
	<td>$employee.getFullName()</td>
</tr>

---------------------------------------------------------------------------
The work around is to change the access of the Employee's
supertype to public:
---------------------------------------------------------------------------

public interface EmployeeBase {
	..........
}

When supertype of Employee has public access Velocity does know about
methods coming from supertype and
therefore generated html is correct:

<tr>
	<th align='right'>Employee First Name:</th>
	## Executing a method that is declared in the interface with public access
(i.e. Employee interface)
	<td>First Name</td>
</tr>

<tr>
	<th align='right'>Employee Full Name:</th>
	## Executing a method that is declared in the interface with package access
(i.e. EmployeeBase interface)
	<td>Full Name</td>
</tr>



---------------------------------------------------------------------------
Conclusion
---------------------------------------------------------------------------
If an interface (class) is declared public (Employee) and it extends another
interface (class) that has package access
(EmployeeBase) the caller in the different package should see all public
methods that are declared explicitly or
implicitly (through its supertypes) in the public interface. Applying this
to our example the caller (Velocity template)
should see two methods declared in $employee variable (i.e. getFirstName()
from Employee and getFullName() from EmployeeBase).


I greatly appreciate your time and assistance on this matter.


Kind regards,


Alex.




---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org


Re: Can't reference methods from supertype that has package access

Posted by Izzy Alanis <iz...@gmail.com>.
Your post sounded weird, so I tried it with a simple test case and
couldn't reproduce the behavior you observed... Are you sure your
getFullName method isn't just returning null under some circumstances?

----------------------------------------
package package1;

interface Interface1A {
    public String getFoo();
}
----------------------------------------
package package1;

public interface Interface1B extends Interface1A {
    public String getBar();
}
----------------------------------------
package package2;

public class TestClass implements package1.Interface1B {
    public String getBar() {
        return "Bar";
    }
    
    public String getFoo() {
        return "Foo";
    }
}
----------------------------------------
package package2;

import java.io.PrintWriter;
import java.io.StringReader;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;

public class Tester {
    
    public static void main(String[] args) throws Exception {
        package1.Interface1B testObject = new package2.TestClass();
        
        VelocityEngine velocityEngine = new VelocityEngine();
        velocityEngine.init();
        
        VelocityContext context = new VelocityContext();
        context.put("testObject", testObject);

        String template = "foo = $testObject.foo\nbar = $testObject.bar\n";
        
        PrintWriter out = new PrintWriter(System.out);
        velocityEngine.evaluate(context, out, null, new StringReader(template));
        out.flush();
    }
}
----------------------------------------
outputs, as expected:

foo = Foo
bar = Bar

----------------------
Velocity is using reflection to call the methods on your object, and
doesn't care as much about the interfaces declared as it cares about
the methods implemented by the instance variable you place in the
context (if that makes sense).

 - Izzy


On Fri, 25 Jun 2004 16:18:56 +1000, Alexandre Akoulov
<sa...@bisinfo.com.au> wrote:
> 
> Hi all,
> 
> I'd greatly appreciate if you could shed some light on the following issue.
> 
> ---------------------------------------------------------------------------
> Problem description (on Velocity 1.4)
> ---------------------------------------------------------------------------
> 
> If a public interface (class) extends another interface (class) that has
> package access Velocity only sees methods that
> are declared in the public interface when a variable of public interface
> type is used in Velocity template.
> 
> It seems that Velocity does not see methods that are declared in the public
> interface's
> parent, which has package access.
> 
> If supertype (parent of public interface) has public access Velocity sees
> methods declared both in public interface
> and its supertype.
> 
> The following example demonstrates this problem.
> 
> ---------------------------------------------------------------------------
> Package "employee" has the following interfaces and classes defined:
> ---------------------------------------------------------------------------
> 
> // Interface that is only visible to classes/interfaces defined in the same
> // package (i.e. "employee" package)
> interface EmployeeBase {
>        // The only method
>        public String getFullName();
> }
> 
> // Interface that is visible to everyone. All methods declared in this
> interface and its supertypes
> // are visible to everyone
> public interface Employee extends EmployeeBase {
>        // Additional method to the ones declared in EmployeeBase
>        public String getFirstName();
> }
> 
> ---------------------------------------------------------------------------
> Package "renderers" has got the following class:
> ---------------------------------------------------------------------------
> 
> public class EmployeeRenderer {
>      // Renders employee html using Velocity
>      public void render(java.io.Writer writer) throws Exception {
>        org.apache.velocity.VelocityContext context = getContext();
>            org.apache.velocity.Template template = getTemplate();
> 
>             // Get new employee
>            employee.Employee employee = getEmployee();
>            // Place employee into the velocity context
>            context.put("employee", employee);
>            // Merge into the velocity template
>            template.merge(context, writer);
>     }
> }
> 
> ---------------------------------------------------------------------------
> In the velocity template:
> ---------------------------------------------------------------------------
> 
> <tr>
>        <th align='right'>Employee First Name:</th>
>        ## Executing a method that is declared in the interface with public access
> (i.e. Employee interface)
>        <td> $employee.getFirstName()</td>
> </tr>
> 
> <tr>
>        <th align='right'>Employee Full Name:</th>
>        ## Executing a method that is declared in the interface with package access
> (i.e. EmployeeBase interface)
>        <td>$employee.getFullName()</td>
> </tr>
> 
> ---------------------------------------------------------------------------
> The Problem is that Velocity does not seem to recognise that  $employee
> variable (i.e. employee.Employee interface) has getFullMethod as generated
> html has the following:
> ---------------------------------------------------------------------------
> 
> <tr>
>        <th align='right'>Employee First Name:</th>
>        ## Executing a method that is declared in the interface with public access
> (i.e. Employee interface)
>        <td>First Name</td>
> </tr>
> 
> <tr>
>        <th align='right'>Employee Full Name:</th>
>        ## Executing a method that is declared in the interface with package access
> (i.e. EmployeeBase interface)
>        <td>$employee.getFullName()</td>
> </tr>
> 
> ---------------------------------------------------------------------------
> The work around is to change the access of the Employee's
> supertype to public:
> ---------------------------------------------------------------------------
> 
> public interface EmployeeBase {
>        ..........
> }
> 
> When supertype of Employee has public access Velocity does know about
> methods coming from supertype and
> therefore generated html is correct:
> 
> <tr>
>        <th align='right'>Employee First Name:</th>
>        ## Executing a method that is declared in the interface with public access
> (i.e. Employee interface)
>        <td>First Name</td>
> </tr>
> 
> <tr>
>        <th align='right'>Employee Full Name:</th>
>        ## Executing a method that is declared in the interface with package access
> (i.e. EmployeeBase interface)
>        <td>Full Name</td>
> </tr>
> 
> ---------------------------------------------------------------------------
> Conclusion
> ---------------------------------------------------------------------------
> If an interface (class) is declared public (Employee) and it extends another
> interface (class) that has package access
> (EmployeeBase) the caller in the different package should see all public
> methods that are declared explicitly or
> implicitly (through its supertypes) in the public interface. Applying this
> to our example the caller (Velocity template)
> should see two methods declared in $employee variable (i.e. getFirstName()
> from Employee and getFullName() from EmployeeBase).
> 
> I greatly appreciate your time and assistance on this matter.
> 
> Kind regards,
> 
> Alex.
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: velocity-user-help@jakarta.apache.org
> 
>

---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org